Sobrescrevendo a API Expresso
A API do Expresso consiste de vários métodos e propriedades nos objetos de solicitação e resposta. Estas são herdadas pelo protótipo. Há dois pontos de extensão para a API Express:
- Os protótipos globais em
express.requesteexpress.response. - Protótipos específicos de aplicativo em
app.requesteapp.response.
Alterar os protótipos globais afetará todos os aplicativos do Express carregados no mesmo processo. Se desejar, alterações podem ser feitas especificamente no aplicativo, alterando apenas os protótipos específicos do aplicativo após criar um novo aplicativo.
Métodos
Você pode substituir a assinatura e o comportamento dos métodos existentes com o seu próprio, atribuindo uma função personalizada.
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'];A implementação acima altera completamente a assinatura original de res.sendStatus. Agora aceita um código de estado, um tipo de codificação e a mensagem a ser enviada ao cliente.
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.
O método sobrescrito agora pode ser usado dessa maneira:
res.sendStatus(404, 'application/json', '{"error":"resource not found"}');propriedades
As propriedades da API Expresso também são:
- Propriedades atribuídas (ex:
req.baseUrl,req.originalUrl) - Definido como getters (ex:
req.secure,req.ip)
Uma vez que as propriedades da categoria 1 são dinamicamente atribuídas aos objetos request e response no contexto do ciclo atual de resposta de solicitação, seu comportamento não pode ser substituído.
As propriedades da categoria 2 podem ser substituídas usando a API de extensões de API Express.
O código a seguir reescreve como o valor de req.ip deve ser derivado. Agora, ele simplesmente retorna o valor do cabeçalho de solicitação 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.
Protótipo
Para fornecer a API Express, os objetos de solicitação/resposta passados para Express (via app(req, res), por exemplo) precisam herdar do mesmo tipo de cadeia. Por padrão, isto é http.IncomingRequest.prototype para a solicitação e http.ServerResponse.prototype para a resposta.
Se necessário, recomenda-se que isso seja feito apenas a nível da aplicação, e não a nível global. Além disso, tenha cuidado para que o protótipo usado corresponda à funcionalidade o mais próximo possível dos protótipos padrão.
// 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);