Traduire cette page

Écriture de middleware pour utilisation dans les applications Express

Aussi, la fonction callback de la route du chemin racine utilise la propriété que la fonction middleware ajoute à req (l’objet de requête). L’application utilise maintenant la fonction middleware requestTime.

Les fonctions Middleware peuvent effectuer les tâches suivantes :

  • Exécuter n’importe quel code.
  • Effectuez des modifications à la requête et aux objets de réponse.
  • Termine le cycle de réponse de la requête.
  • Appelez le prochain middleware dans la pile.

Si la fonction middleware actuelle ne met pas fin au cycle de réponse de requête, elle doit appeler next() pour passer le contrôle à la prochaine fonction du middleware. Sinon, la demande sera laissée en suspens.

La figure suivante montre les éléments d’un appel de fonction middleware :

Elements of a middleware function call

À partir de Express 5, les fonctions middleware qui retournent une Promise appelleront next(value) quand elles rejettent ou lancent une erreur. next sera appelé avec la valeur rejetée ou avec l’erreur levée.

Exemple

Voici un exemple de simple application “Hello World” Express. Le reste de cet article va définir et ajouter trois fonctions middleware à l’application : un appelé myLogger qui affiche un message de log simple. on appelle requestTime que affiche l’horodatage de la requête HTTP, et un appelé validateCookies qui valide les cookies entrants.

index.cjs
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000);

Fonction Middleware myLogger

Voici un exemple simple d’une fonction middleware appelée “myLogger”. Cette fonction affiche seulement “LOGGED” lorsqu’une requête vers l’application passe à travers elle. La fonction middleware est assignée à une variable nommée myLogger.

const myLogger = function (req, res, next) {
console.log('LOGGED');
next();
};

Here myLogger is defined on its own rather than passed directly to app.use(), so TypeScript has no context to infer its parameters and they are annotated explicitly. You can instead type the whole function as RequestHandler, which types req, res, and next for you. When the middleware is written inline in the app.use() call, Express infers those three parameters and no annotations are needed.

Notez l’appel ci-dessus à next(). Appeler cette fonction appelle la prochaine fonction du middleware dans l’application. La fonction next() n’est pas une partie du noeud. s ou API Express, mais est le troisième argument qui est passé à la fonction middleware. La fonction next() pourrait être nommée quoi que ce soit, mais par convention elle est toujours nommée “next”. Pour éviter toute confusion, utilisez toujours cette convention.

Pour charger la fonction middleware, appelez app.use(), en spécifiant la fonction middleware. Par exemple, le code suivant charge la fonction middleware myLogger avant la route vers le chemin racine (/).

index.cjs
const express = require('express');
const app = express();
const myLogger = function (req, res, next) {
console.log('LOGGED');
next();
};
app.use(myLogger);
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000);

Chaque fois que l’application reçoit une demande, elle affiche le message “LOGGGED” vers le terminal.

L’ordre de chargement du middleware est important : les fonctions du middleware qui sont chargées en premier sont également exécutées en premier.

Si myLogger est chargé après la route vers le chemin racine, la requête ne l’atteint jamais et l’application n’affiche pas “LOGGED”, parce que le gestionnaire de route du chemin racine termine le cycle de réponse de requête.

La fonction du middleware myLogger affiche simplement un message, passe ensuite la requête à la prochaine fonction middleware de la pile en appelant la fonction next().

Middleware fonction requestTime

Ensuite, nous allons créer une fonction middleware appelée “requestTime” et ajouter une propriété appelée requestTime à l’objet requête.

Because the middleware adds a property to req, extend the request type in TypeScript with declaration merging. Declare the property (as optional, since a middleware may not run for every request) in a .d.ts file that is part of your project:

types/express.d.ts
declare global {
namespace Express {
interface Request {
requestTime?: number;
}
}
}
export {};

TypeScript picks up the file automatically, so no tsconfig.json change is needed unless you have set a custom include that does not cover its location. See Extending the API in TypeScript for adding other custom properties and methods.

const requestTime = function (req, res, next) {
req.requestTime = Date.now();
next();
};

The app now uses the requestTime middleware function. Also, the callback function of the root path route uses the property that the middleware function adds to req (the request object).

index.cjs
const express = require('express');
const app = express();
const requestTime = function (req, res, next) {
req.requestTime = Date.now();
next();
};
app.use(requestTime);
app.get('/', (req, res) => {
let responseText = 'Hello World!<br>';
responseText += `<small>Requested at: ${req.requestTime}</small>`;
res.send(responseText);
});
app.listen(3000);

Lorsque vous faites une demande à la racine de l’application, l’application affiche maintenant l’horodatage de votre requête dans le navigateur.

format@@0 Middleware function validateCookies

Enfin, nous allons créer une fonction middleware qui valide les cookies entrants et envoie une réponse 400 si les cookies sont invalides.

Voici un exemple de fonction qui valide les cookies avec un service asynchrone externe.

async function cookieValidator(cookies) {
try {
await externallyValidateCookie(cookies.testCookie);
} catch {
throw new Error('Invalid cookies');
}
}

Le middleware validateCookies retourne une Promesse que si le rejet déclenchera automatiquement notre gestionnaire d’erreurs. Ici, nous utilisons le middleware cookie-parser pour analyser les cookies entrants de l’objet req et les passer à notre fonction cookieValidator.

index.cjs
const express = require('express');
const cookieParser = require('cookie-parser');
const cookieValidator = require('./cookieValidator');
const app = express();
async function validateCookies(req, res, next) {
await cookieValidator(req.cookies);
next();
}
app.use(cookieParser());
app.use(validateCookies);
// error handler
app.use((err, req, res, next) => {
res.status(400).send(err.message);
});
app.listen(3000);

Notez comment next() est appelé après wait cookieValidator(req.cookies). Cela garantit que si cookieValidator résoud, le prochain middleware de la pile sera appelé. Si vous passez quelque chose à la fonction next() (sauf la chaîne 'route' ou 'router'), Express considère que la requête actuelle est une erreur et ignorera toute fonction de routage et de middleware qui ne gère pas les autres fonctions de routage.

Parce que vous avez accès à l’objet requête, à l’objet de réponse, à la prochaine fonction du middleware dans la pile, et à l’ensemble du nœud. s API, les possibilités avec les fonctions du middleware sont infinies.

Pour plus d’informations sur le middleware Express, voir : Utiliser un middleware Express.

Logiciel middleware configurable

Si vous avez besoin que votre middleware soit configurable, exportez une fonction qui accepte un objet d’options ou d’autres paramètres, qui retourne ensuite l’implémentation du middleware en fonction des paramètres d’entrée.

my-middleware.cjs
module.exports = function (options) {
return function (req, res, next) {
// Implement the middleware function based on the options object
next();
};
};

Le middleware peut maintenant être utilisé comme montré ci-dessous.

index.cjs
const mw = require('./my-middleware.cjs');
app.use(mw({ option1: '1', option2: '2' }));

Reportez-vous à cookie-session et compression pour des exemples de middleware configurables.