Outrepasser l'API Express
L’API Express se compose de différentes méthodes et propriétés sur les objets de requête et de réponse. Celles-ci sont héritées du prototype. Il y a deux points d’extension pour l’API Express :
- Les prototypes globaux à
express.requestetexpress.response. - Prototypes spécifiques à l’application à
app.requestetapp.response.
Modifier les prototypes globaux affectera toutes les applications Express chargées dans le même processus. Si vous le souhaitez, les modifications peuvent être apportées à l’application en modifiant uniquement les prototypes spécifiques à l’application après avoir créé une nouvelle application.
Méthodes
Vous pouvez remplacer la signature et le comportement des méthodes existantes avec vos propres méthodes en assignant une fonction personnalisée.
Following is an example of overriding the behavior of res.sendStatus.
app.response.sendStatus = function (statusCode, type, message) { // code is intentionally kept simple for demonstration purpose return this.contentType(type).status(statusCode).send(message);};import { type Response } from 'express';
// Broaden the type of sendStatus so call sites accept the new arguments.declare module 'express-serve-static-core' { interface Response { sendStatus(statusCode: number, type: string, message: string): this; }}
app.response.sendStatus = function ( this: Response, statusCode: number, type: string, message: string) { // code is intentionally kept simple for demonstration purpose return this.contentType(type).status(statusCode).send(message);} as Response['sendStatus'];L’implémentation ci-dessus modifie complètement la signature originale de res.sendStatus. Il accepte maintenant un code de statut, un type d’encodage, et le message à envoyer au client.
In TypeScript, augmenting express-serve-static-core adds the new overload to the Response type so call sites such as res.sendStatus(404, 'application/json', body) type-check. The assignment is cast with as Response['sendStatus'] because replacing a method with a different signature cannot be checked against the original declaration.
La méthode surchargée peut maintenant être utilisée de cette manière:
res.sendStatus(404, 'application/json', '{"error":"resource not found"}');Propriétés
Les propriétés de l’API Express sont soit :
- Propriétés assignées (ex:
req.baseUrl,req.originalUrl) - Défini comme getters (ex:
req.secure,req.ip)
Puisque les propriétés de la catégorie 1 sont assignées dynamiquement sur les objets request et response dans le contexte du cycle de réponse de la requête courante, leur comportement ne peut pas être remplacé.
Les propriétés de la catégorie 2 peuvent être écrasées en utilisant l’API des extensions API Express.
Le code suivant réécrit comment la valeur de req.ip doit être dérivée. Maintenant, il retourne simplement la valeur de l’en-tête de la requête Client-IP.
Object.defineProperty(app.request, 'ip', { configurable: true, enumerable: true, get() { return this.get('Client-IP'); },});import { type Request } from 'express';
Object.defineProperty(app.request, 'ip', { configurable: true, enumerable: true, get(this: Request) { return this.get('Client-IP'); },});Extending the API in TypeScript
The sections above override members that Express already provides. To add your own properties or
methods to the request or response, describe them to TypeScript with
declaration merging on the
Express namespace. Put the augmentation in a .d.ts file that is part of your project. No
tsconfig.json change is needed unless a custom include does not cover its location.
For example, an authentication middleware may attach a user to the request, and you might add a
sendError helper to the response:
interface User { id: string; name: string;}
declare global { namespace Express { interface Request { user?: User; } interface Response { sendError(status: number, message: string): this; } }}
export {};The additions are now known throughout the application:
import { type Request, type Response, type NextFunction } from 'express';
app.use((req: Request, res: Response, next: NextFunction) => { req.user = { id: '1', name: 'Tobi' }; next();});
app.response.sendError = function (this: Response, status: number, message: string) { return this.status(status).json({ error: message });};
app.get('/', (req: Request, res: Response) => { if (!req.user) { res.sendError(401, 'unauthorized'); return; } res.send(req.user.name);});Declare custom request properties as optional (user?). The type applies to every request, but
TypeScript cannot know which middleware ran before a given handler, so a required property would be a
false guarantee. Check for the value (as with if (!req.user) above) before relying on it.
Adding a new method needs no cast, unlike overriding an existing method with a different signature, because the method did not previously exist on the type.
Prototype
Afin de fournir l’API Express, les objets de requête/réponse passés à Express (via app(req, res), par exemple) doivent hériter de la même chaîne de prototypes. Par défaut, c’est http.IncomingRequest.prototype pour la requête et http.ServerResponse.prototype pour la réponse.
Sauf si nécessaire, il est recommandé de le faire uniquement au niveau de l’application, plutôt qu’au niveau mondial. Veillez également à ce que le prototype utilisé corresponde le plus près possible à la fonctionnalité des prototypes par défaut.
// Use FakeRequest and FakeResponse in place of http.IncomingRequest and http.ServerResponse// for the given app referenceObject.setPrototypeOf(Object.getPrototypeOf(app.request), FakeRequest.prototype);Object.setPrototypeOf(Object.getPrototypeOf(app.response), FakeResponse.prototype);