# Middlewares
Les middlewares sont très répandus dans le développement backend, ceux-ci permettent d'éviter de vous répéter, de clarifier votre code et de mieux l'organiser.
Le système utilisé par ce module est basé sur le fonctionnement des middleware de koa
.
# Construction et utilisation d'un middleware basé sur une fonction
Un middleware est une fonction qui est exécutée avant la fonction principale d'une requête. Celle-ci permet par exemple de vérifier qu'un utilisateur est authentifié.
Ici nous allons créer un middleware qui vérifie la valeur d'un argument.
# 1. Déclaration
Déclarons la fonction
import { Context, Next } from "graphql-composer";
async function verifiyArgs(args, context: Context, next: Next) {
}
# 2. Validation
Si la condition est remplie, il faudra dire à notre middleware qu'il peut passer au middleware suivant, ceci se fait avec le paramètre next
qui est une fonction asynchrone à appeler.
Si next
n'est pas appelé, le middleware suivant n'est simplement pas exécuté.
Si vous ne mettez pas d'
await
avantnext()
le middleware courant ne va pas attendre la fin de l'exécution du middleware suivant pour exécuter la suite de son code.
import { Context, Next } from "graphql-composer";
async function verifiyArgs(args, context: Context, next: Next) {
if (args.count > 0) {
await next();
}
throw new Error("Count must be greater than 0");
}
# 3. Utilisation
Votre middleware peut être appliqué avec le décorateur @Middlewares
à:
- Un resolver
- Un ObjectType
- Une InterfaceType
- Une query
- Une mutation
- Une subscription
# Avec @Query
ou @Mutation
ou @Subscription
@Resolver()
class Resolver {
@Query()
@Middlewares(verifyArgs)
query(@Arg("count") count: number) {
// ...
}
@Mutation()
@Middlewares(verifyArgs)
mutation(@Arg("count") count: number) {
// ..
}
@Subscription({ subscribe: () => pubsub.asyncIterator("NOTIF") })
@Middlewares(verifyArgs)
subscription(@Arg("count") count: number) {
// ..
}
}
# Avec @Resolver
(ou ObjectType
/ InterfaceType
)
Ceci va appliquer le middleware sur toutes les méthodes du resolver.
Les middlewares appliqués à @Resolver
vont être exécutés avant les middlewares sur les méthodes de la class.
@Resolver()
@Middlewares(verifyArgs)
class Resolver {
@Query()
query(@Arg("count") count: number) {
// ...
}
@Mutation()
mutation(@Arg("count") count: number) {
// ..
}
@Subscription({ subscribe: () => pubsub.asyncIterator("NOTIF") })
subscription(@Arg("count") count: number) {
// ..
}
}
# Construction et utilisation d'un middleware basé sur une class
Cela peut être plus "propre" d'utiliser une classe pour déclarer un middleware plutôt qu'une fonction directement. Pour cela vous pouvez utiliser la class Middleware
fournie par graphql-composer-decorators
.
# 1. Déclaration
Déclarons la class
import { Context, Next } from "graphql-composer";
import { Middleware } from "graphql-composer-decorators";
class ArgsVerificator extends Middleware {
async resolve(args, context: Context, next: Next) {
}
}
# 2. Validation
Si la condition est remplie, il faudra dire à notre middleware qu'il peut passer au middleware suivant, ceci se fait avec le paramètre next
qui est une fonction asynchrone à appeler.
Si next
n'est pas appelé, le middleware suivant n'est simplement pas exécuté.
Si vous ne mettez pas d'
await
avantnext()
le middleware courant ne va pas attendre la fin de l'exécution du middleware suivant pour exécuter la suite de son code.
import { Context, Next } from "graphql-composer";
import { Middleware } from "graphql-composer-decorators";
class ArgsVerificator extends Middleware {
async resolve(args, context: Context, next: Next) {
if (args.count > 0) {
await next();
}
throw new Error("Count must be greater than 0");
}
}
# 3. Utilisation
Ils sont utilisables de la même façon qu'un middleware basé sur une fonction
Votre middleware peut être appliqué avec le décorateur @Middlewares
à:
- Un resolver
- Un ObjectType
- Une InterfaceType
- Une query
- Une mutation
- Une subscription
# Avec @Query
ou @Mutation
ou @Subscription
@Resolver()
class Resolver {
@Query()
@Middlewares(ArgsVerificator)
query(@Arg("count") count: number) {
// ...
}
@Mutation()
@Middlewares(ArgsVerificator)
mutation(@Arg("count") count: number) {
// ..
}
@Subscription({ subscribe: () => pubsub.asyncIterator("NOTIF") })
@Middlewares(ArgsVerificator)
subscription(@Arg("count") count: number) {
// ..
}
}
# Avec @Resolver
(ou ObjectType
/ InterfaceType
)
Ceci va appliquer le middleware sur toutes les méthodes du resolver.
Les middlewares appliqués à @Resolver
vont être exécutés avant les middlewares sur les méthodes de la class.
@Resolver()
@Middlewares(ArgsVerificator)
class Resolver {
@Query()
query(@Arg("count") count: number) {
// ...
}
@Mutation()
mutation(@Arg("count") count: number) {
// ..
}
@Subscription({ subscribe: () => pubsub.asyncIterator("NOTIF") })
subscription(@Arg("count") count: number) {
// ..
}
}
← Resolver Description →