mirror of
https://github.com/nestjs/nest.git
synced 2026-10-28 09:45:43 +08:00
* feat(node): add a native node http platform adapter
Add @nestjs/platform-node, an HTTP adapter built directly on the
node:http and node:https modules. Routes use the same path syntax as
with the Express adapter and are matched through a find-my-way radix
tree; middleware runs in an Express-compatible stack. Body parsing,
CORS, static assets and template rendering are built in.
* test(node): run the shared integration suites against the adapter
* chore: add node and nest-node targets to the benchmarks
* feat(node): limit route parameters to 100 characters
As with Fastify, a route no longer matches when one of its parameters
is longer than 100 characters (decoded): the request falls through to
the next matching route, or gets a 404. Wildcards are not limited.
* feat(node): add the multer file upload interceptors
Ship FileInterceptor, FilesInterceptor, FileFieldsInterceptor,
AnyFilesInterceptor, NoFilesInterceptor and MulterModule with the
package, as @nestjs/platform-express does, instead of borrowing them
from it.
* docs(node): add the package readme
* test(node): map @nestjs/platform-node in the integration tsconfigs
* fix(node): match routes that differ only by parameter names
Routes of the same shape registered with different parameter names
(GET /users/:id for one version, GET /users/:userId for another) now
share one route and pass control to each other through next(), as with
Express, and each handler sees the parameter names of its own route.
Text right after a parameter ("/users/:id@profile") no longer ends up
in the parameter's name.
* test(node): listen on 127.0.0.1 in the node adapter specs
Use listenOnLoopback() in the Node adapter's own supertest specs, as
* fix(node): fix edge cases in responses, routing and body parsing
- next(null), next(false) and other falsy values are no errors, as
with Express, so that "cb(err => next(err))" works
- req.path is the path the router matches (decoded, absolute-form
targets resolved), so that middleware checking it sees that path
- an empty 204, 205 or 304 reply drops its Content-Type, as does
sendStatus() for those statuses; a StreamableFile error response
sends its own Content-Length rather than the file's
- res.type() looks up extensions as Express does, send() and json()
send a Content-Length in answer to HEAD requests, and a Referrer
header wins over Referer
- body parsers call next() when the client is already gone, report a
mid-body abort as "request.aborted", validate parameterLimit and
depth, take a null limit for the default, keep the status of errors
thrown by verify, reject whitespace-only JSON, drop a UTF-8 BOM, and
reject "__proto__" keys in urlencoded bodies with 'error'
* test(node): add unit tests
Cover the adapter, the request and response helpers, the router and
its route tables, the body parsers and the view renderer.
* chore: write the raw node benchmark headers in a single call
* fix(node): decode windows-1252 bodies the same on every node version
TextDecoder in some Node.js 22 and 24 releases (22.15, 24.4 among them) decodes windows-1252, and labels mapped to it such as cp1252, as ISO-8859-1, so bytes 0x80-0x9F came out as C1 controls instead of characters like the euro sign. Map those bytes ourselves.
* feat(node): add res.redirect(), res.locals and req.is()
Express-compatible helpers that common middleware relies on (passport and OAuth flows redirect, middleware passes data along in res.locals, some check the request type with req.is()). res.redirect() encodes the Location, negotiates a plain text or HTML note from Accept and adds Accept to Vary, matching Express 5.
* fix(node): match routes with the method set by earlier middleware
The router read req.method once per request; Express reads it for every layer, so middleware such as method-override could not change which route runs. Read it per layer.
* feat(node): add res.append(), res.cookie() and req.app for middleware
Popular Express middleware calls these: express-rate-limit sets its headers with res.append() and reads req.app.get('trust proxy'), csrf-csrf sets its cookie with res.cookie(). res.clearCookie() comes along. They follow Express 5, using the same cookie and cookie-signature packages; req.app only reports the adapter's fixed settings ('trust proxy' is false).
* fix(node): match wildcard routes and fall through to other routes
- a route such as "/admin/{*path}" or "/admin/{:id}" no longer matches "/admin" (find-my-way's ignoreTrailingSlash matched its "/admin/" variant there), so it matches the same paths as its middleware, as with Express
- once every handler of the most specific route calls next(), the other routes matching the path run, each with its own parameters, so a version- or host-filtered handler that does not apply falls through to ":id" as with Express and Fastify
- a wildcard is split before it is decoded, keeping an encoded "/" within its segment
* fix(node): pass errors from middleware on to exception filters as is
mapException() turned http-errors-style errors into a new HttpException, so a @Catch(MyError) filter and anything reading the error's code (EBADCSRFTOKEN, ...) no longer saw them. Return them unchanged, as the Express adapter does; Nest's exception filter answers them with their status and message as before.
* fix(node): pass the views directory to view engines such as hbs
res.render() in Express passes its settings, including "views" and "view engine", to the engine's __express(); hbs reads "views" to find layouts, so @Render() with hbs failed with a 500. Pass them the same way.
* fix(node): align the body parsers with body-parser 2
- read the charset with content-type 2, as body-parser does, so a Content-Type with a trailing ";" keeps its charset
- accept limit: Infinity and the tb/pb units (NaN and negative limits still throw)
- add the urlencoded defaultCharset, charsetSentinel and interpretNumericEntities options
- pick the byte order of "utf-16" bodies from the byte order mark, or else the content, as iconv-lite does
* fix(node): send binary, redirects and 404s as other adapters do
- send typed arrays and DataViews as binary, as Buffers already were (as Fastify does)
- @Redirect() sends the note and "Vary: Accept" res.redirect() sends, as with Express
- res.send() sends numbers and booleans as JSON, as Express 5 does
- res.json() sets no Content-Type when serializing the body throws
- the 404 for a request outside the global prefix echoes the path as received rather than decoded, with "X-Content-Type-Options: nosniff" and "Content-Security-Policy: default-src 'none'", as Express' final handler does
* test(node): expect the bare path to miss an optional wildcard route
As with Express, "/v1/users/" reaches the converted "{*path}" catch-all but "/v1/users" does not; the spec had encoded the old Node adapter behavior.
* fix(node): match every path case-sensitively
find-my-way routes were case-sensitive while the routes matched with path-to-regexp (wildcards, optional groups) and the middleware were not, so "GET /CATS" ran the middleware of "cats" and then got a 404, and "/ADMIN/x" reached the "admin" catch-all. Match all of them case-sensitively, as find-my-way does by default (and Fastify); the case-insensitive alternative would lowercase every request path.
* feat(node): make the parameter limit configurable and answer 414
new NodeAdapter({ maxParamLength }) sets the longest route parameter a route matches (100 by default, as with Fastify). A request whose parameter is longer still falls through to another matching route, such as a sibling wildcard; when none matches, it now gets a 414 (URI Too Long) rather than a 404, as with Fastify. The 414 goes through Nest's exception handling like other errors, so filters can catch it.
* test: compare the http adapters on routing, errors, views and parsing
A new integration suite runs the same applications and requests on the Express, Fastify and Node adapters, where they support the feature, with the same expectations:
- wildcard and optional-group routes, and which requests their middleware sees
- falling through to less specific routes from version filters (header, media type, custom, neutral, several versions, all methods, global prefix, URI) and host filters
- errors raised by middleware, as @Catch() filters and Nest's exception handling see them
- @Render() with an engine that finds partials through the views directory
- @Redirect(), res.send() and binary bodies
- body parser charsets, limits and urlencoded charset options
- Node specifics: the route parameter limit and its 414, case-sensitive paths, and the final 404 outside the global prefix
* feat(node): let responses send files as express does
Adds Express' res.sendFile() on the same send package: Content-Type, Content-Length, Last-Modified, ETag, ranges and 304s, the root, headers, maxAge, dotfiles and etag options, and a callback for the outcome. Without a callback, a failure goes to the error-handling middleware and Nest's exception filters, as Express does through next(): a missing file is a 404 and a directory answers like an unmatched route. The adapter reaches its router from the request's server for that, so nothing is stored per request.
@nestjs/serve-static calls it for its index.html fallback. send and on-finished were already loaded through serve-static; an interleaved wrk comparison (4 rounds), the router microbenchmark and the import time show no difference.
Also sends the JSON error body of a reply whose Content-Type was not JSON as application/json; charset=utf-8, as Express ends up doing.
* test(node): cover the shutdown 503 while the hooks run
The adapter already answered 503 with Connection: close once beforeClose() ran, from the first layer of the router, before Nest middleware, and destroyed connections only in close(). Cover what #18101 covers for Fastify's return503OnClosing: a request during a slow onModuleDestroy() gets the 503 without reaching middleware, requests keep being served without the option, and forceCloseConnections leaves kept-alive sockets open during the hooks.
The 503 now says Content-Type: text/plain; charset=utf-8, like Fastify's and the adapter's final handler.
* fix(node): match excluded routes like the router does
Report through HttpServer.getRouteMatchingOptions() that the router
matches paths case-sensitively and ignores a trailing slash, so that
MiddlewareConsumer.exclude() compiles the excluded routes the same way.
* fix(node): expose package.json in the exports map
As the other packages do since #18122.
* chore(node): align the package version with the 12.1.3 release
The v12.1.3 release bumped the exact @nestjs/common and @nestjs/core
devDependencies of the other packages. Left at 12.1.2 here, they no
longer matched the workspace once master was merged in, so npm
installed both from the registry under packages/platform-node and the
adapter ran against its own copies: its HttpException, StreamableFile
and VERSION_NEUTRAL were not the ones the core checks for.
* Update packages/platform-node/body-parser/body-parser.ts
Co-authored-by: Roman Khegay <rk@garuna.dev>
* perf(node): parse a repeated content-type charset once
Clients send the same Content-Type with every request, so the charset of the last header parsed is kept instead of parsing the header again. Media types without parameters still return before it.
Co-authored-by: Roman Khegay <rk@garuna.dev>
* test(node): cover a content-type that changes between requests
The same parser reads Latin-1, UTF-8, no charset and Latin-1 again, so a charset cache that misses a change fails.
* Update packages/platform-node/body-parser/body-parser.ts
Co-authored-by: Roman Khegay <rk@garuna.dev>
* Revert "Update packages/platform-node/body-parser/body-parser.ts"
This reverts commit 88e446db1b, which applied the charset cache suggestion a second time on top of 13619b662e, declaring the cache twice and leaving a partial copy of getCharset().
* chore(node): align the package version with the 12.2.0 release
As every sibling did in the release, so that the workspace links the
adapter to this checkout's @nestjs/common and @nestjs/core.
* fix(node): answer request targets that are not a path with 404
Node.js accepts request targets such as "*admin/users", which
find-my-way routes as "/admin/users", while no middleware path matches
them, so the route ran without its middleware. "OPTIONS *" got the
"OPTIONS /" route. RouteTable.lookup() now matches no path that does not
start with "/", so these get the not-found handler, as on Express and
Fastify (a03c7a1db).
Co-authored-by: Roman Khegay <rk@garuna.dev>
* fix(node): send the standard body for an exception wrapping an error
JSON.stringify() sends the enumerable properties of an Error, e.g. the
request config of an HTTP client error, so an Error body with an error
status now gets the standard body of the status, as on Express
(876a182c6). An object error body without a "statusCode" of its own also
goes out as JSON when the route set another Content-Type (7dc6e349d).
Co-authored-by: Roman Khegay <rk@garuna.dev>
* fix(node): handle a failed streamable file and one for a head request
A source that failed before the reply (e.g. while an interceptor
awaited) has already emitted its "error" event, so the request hung until
the client gave up; it now goes to the error handler of the file, as on
Express and Fastify (1933cc9ed). A HEAD response no longer pipes the whole
source, which Node discards without applying backpressure; it ends once
the source is readable (8b8e8396f). The specs expect the "Bad Request" the
default error handler now sends (2f28d91af).
Co-authored-by: Roman Khegay <rk@garuna.dev>
* fix(node): run wildcard middleware on "/api/" for a named wildcard
The exact "/api" entry skipped "/api/" so that the middleware would not
run twice next to "/api/{*path}", which left "/api/*path" (one more
segment needed) running it 0 times there. The core now runs a middleware
for the first of its paths that matches a request only (fb8c2cac7), so
the entry is registered as is, as on Express (b75244ffd).
Co-authored-by: Roman Khegay <rk@garuna.dev>
* fix(node): parse quoted media type version parameters
The copy of getMediaTypeVersion() is master's (c8923bd7c): quoted
values are unescaped, and "," or ";" inside quotes no longer split the
header, so `Accept: application/json;v="2"` matches version 2, as on
Express and Fastify.
Co-authored-by: Roman Khegay <rk@garuna.dev>
* fix(node): copy the multer fixes of platform-express
Copied again from platform-express: the limit fields of the options
(#18074), the default fieldNestingDepth and fieldArrayIndexLimit
(94fcc9377), removing the uploads of a request a pipe rejected
(acb98de89), and a route's dest replacing the module's storage
(e075cda3c). The parity spec checks the upload directory of Node too.
Co-authored-by: Roman Khegay <rk@garuna.dev>
* fix(node): set the security headers on router error responses
The router answers a request target it cannot decode (a malformed URL,
400) without running any middleware, so the response had none of the
headers set by useSecurityHeaders(). NodeRouter now reports such a
request to onRejectedTarget, where the adapter runs the security hook
for its headers, as the FastifyAdapter does for the errors its router
answers (c04a9182b).
* test(node): expect the sse error event and csrf answers of master
The SSE error event carries "Internal server error" (97ab04494). Node
serves "/api/hooks/github/" with the "github" route, as Express does, so
an exclusion of "hooks/github/*" still leaves it to CSRF protection: a 403
(7b01d0e7a9).
* fix(node): write the html redirect note as express 5.3 does
Express 5.3 (in master's lockfile) sends the HTML note of res.redirect()
with a doctype, a title and a body. The Node response does the same, and
the spec shared by both expects it.
* test(node): wrap the source in a streamable file before destroying it
The source emitted 'error' before StreamableFile attached its listener,
so Vitest reported an uncaught exception and the unit test jobs exited
with code 1 although every test passed. The Express spec on master
creates the file first as well.
* fix(node): map 4xx http-errors errors to http exceptions
As master now does for Express (#18214, #18232) and Fastify (#18239): an
http-errors-style client error, such as a 413 from a body parser or a 403
a middleware passes to next(), reaches exception filters as an
HttpException with its status and the original error as its cause, so
@Catch(HttpException) filters run for it. A 5xx one stays unmapped, so the
built-in exception filter still logs it. The shared middleware errors spec
expects the new behavior on all three adapters.
Co-authored-by: Roman Khegay <rk@garuna.dev>
* fix(node): end a head response for an empty streamable file
A source that has no data, or has already ended, never emits 'readable'
for a listener added that late, so a HEAD request for it never got an
answer. As master now does for Express (#18234), the response also ends on
'end', or right away when the source has already ended.
Co-authored-by: Roman Khegay <rk@garuna.dev>
* fix(node): abort the response when a streamable file fails midway
Since #18220, the default StreamableFile error handler destroys a response
whose headers are out, but the response object the Node adapter handed it
had no destroy(), so it fell back to end() and a file that failed midway
reached the client as a complete 200. The response now has destroy().
Co-authored-by: Roman Khegay <rk@garuna.dev>
* fix(node): handle async request and response hook errors
A request hook that threw or rejected was fire and forget, so an async hook
throwing an UnauthorizedException took the process down with an unhandled
rejection, done(err) still routed the request, and a second done() ran the
handler twice. As the ExpressAdapter does since #18110, the first
completion routes the request or hands its error to the error handlers,
and later errors are logged; a failing response hook is logged too.
Co-authored-by: Roman Khegay <rk@garuna.dev>
* fix(node): resume the error handlers after the one that failed
handleError() always started over from the first layer, so an exception
filter answering with res.sendFile() looped without end when that call
failed as well (a global @Catch() error page and "Range: bytes=99999-" ran
the filter about 44k times in 1.5 s). Like Express' next() does, it now
resumes after the error handler that ran last, and the final handler
answers with a 416 there.
Co-authored-by: Roman Khegay <rk@garuna.dev>
* fix(node): pass res.locals to the views
The res.locals a middleware set never reached a @Render() view, while
Express and @fastify/view merge them into the view data. The data the
handler returns still wins over them, and they win over the engine's
defaultContext, as with Express' res.render().
Co-authored-by: Roman Khegay <rk@garuna.dev>
* fix(node): parse a body with an empty content-encoding or charset
An empty Content-Encoding header got a 415 and an empty charset parameter
was taken as a charset, while Express and Fastify parse such bodies:
body-parser reads an empty encoding as "identity" and an empty charset as
the default one, and so do the Node adapter's parsers now.
Co-authored-by: Roman Khegay <rk@garuna.dev>
* perf(node): skip the qs decoder for form tokens without escapes
The decoder of "qs" replaces "+" and calls decodeURIComponent() for every
key and value of a urlencoded body. A token without "%" or "+" stays as it
is, so it is now returned right away: qs.parse() of a 10-field form runs
1.7x as fast when no field is escaped, and 1.3x as fast with three escaped
fields, with the same output.
Co-authored-by: Roman Khegay <rk@garuna.dev>
* perf(node): decode middleware path parameters only when escaped
decodeURIComponent() is a call into the runtime (about 80 ns) even for a
value without any "%" to decode, which is most of them. The parameters of
middleware paths are now returned as they are in that case.
Co-authored-by: Roman Khegay <rk@garuna.dev>
* test(node): run the cors and middleware spec on the node adapter
The spec #18217 added for Fastify passes on the Node adapter as it is: enableCors() registers the cors middleware ahead of Nest middleware there, as on Express.
* fix(node): leave the text before a wildcard out of it
A wildcard after text in its segment ("v-*rest", or "ab*cd") also matched
that text alone, so GET /files/v- ran the handler without the middleware
of the route, and the value kept the text (['v-abc', 'def']). The
wildcard now starts after it, as with path-to-regexp and Express, and the
route stays in the tree, ahead of a parameter of the same segment. After
a parameter ("/tags/:id-*rest"), where it starts varies, so such a route,
which never matched, is now matched with path-to-regexp.
* fix(node): match routes for every method by specificity
Routes for every method lived in a tree of their own, merged with the
method routes by registration order, so an @All('*') fallback served
GET /cats of a module registered after it. Each method now has one tree,
which also holds the routes for every method and, for HEAD, the GET
routes, so the most specific route wins whatever its method, as with
Fastify. A single find() replaces the HEAD and @All() lookups.
* fix(node): keep catch-all routes with an optional wildcard in the tree
A route with a variant ending with "/" ("/files/{*path}", what the legacy
"files/*" becomes) was only matched with path-to-regexp once the tree
found nothing, so it lost to any other route: GET /files/readme went to
":section/:id", and GET /api/users to an earlier "{*path}" SPA route. Its
other variants now go in the tree, and path-to-regexp only matches the
paths ending with "/", with its own parameters there, as with Express.
* fix(node): try the other routes when one leaves a parameter empty
find-my-way stops at the most specific route, even when it then leaves a
parameter empty, which path-to-regexp and Express never match. For GET
/ext/.gitignore it picked the "/ext/:file.:ext" variant of
"/ext/:file{.:ext}" with an empty "file", and the lookup gave a 404 while
Express answers with { file: '.gitignore' }. Likewise, GET /docs/.env
missed "/docs/*path" next to "/docs/:name.:ext", and GET /files/v-
missed "/files/:id" next to "/files/v-*rest". The first route that
path-to-regexp matches, in registration order, now answers such a
request, as with Express, and "/users//profile" still matches no
"/users/:id/profile" route.
* perf(node): skip the middleware layers and routes of other prefixes
Nest registers a middleware bound to a controller once per route path, so
forRoutes() on 100 controllers ran about 500 path matchers on every
request. lookupRest() ran the matcher of every route after a version miss
(613 RegExp executions with 1000 routes), and so did lookup() for a path
leaving a parameter empty. A layer or route whose literal prefix the path
does not start with now skips the ones registered right after it that
share that prefix, with a single startsWith(): from 30.1k to 69.4k req/s
for the forRoutes() case, and from 19.6k to 48.9k req/s for the version
miss.
* perf(node): decode route parameters only when escaped
As for the middleware paths, decodeParam() and decodeSegment() of the
route table now return a value without "%" as it is, so a wildcard route
no longer calls decodeURIComponent() for each segment of the path (about
5% more req/s for a 5-segment one).
* fix(node): route a path ending with "/" as the path without it
A route with a variant ending with "/" ("/files/{*path}", what the legacy
"files/*" becomes) took every path ending with "/" from the routes
registered after it, as its whole path-to-regexp pattern matched them: GET
/files/readme went to "/files/readme", but GET /files/readme/ to the
catch-all. It now only takes the paths its variants ending with "/" match
("/files/"), so "/admin/" still goes to an "/admin/{*path}" registered
before "/admin", as with Express, and any other path ending with "/" goes
to the route it would go to without it, as exclude() assumes.
* perf(node): try only the routes that can match an empty segment
When find-my-way's route leaves a parameter empty, lookup() tried every
route with path-to-regexp, so GET /acme/res500//profile took about 190 µs
with 2000 "/:tenant/..." routes, and 15 µs with distinct prefixes. A
parameter or wildcard that is a whole segment of its route is only empty
for "/" or a path with an empty segment ("//"), which only routes with a
wildcard, a variant ending with "/" or "//" can match: those are now the
only ones tried, and none for "/" (about 200 ns either way). Routes with
a segment holding text and a parameter ("/ext/:file.:ext") or a wildcard
after text still try every route.
* test(node): cover trailing bytes after a compressed body
Ports body-parser's tests for bytes that arrive after a compressed frame,
which zlib ends the decompression stream on since Node.js 11: the request
still finishes, a late decoder error is swallowed instead of ending the
process, and a body rejected for its charset never creates a decoder. The
parser already keeps an error listener on the decoder once it has read the
body; without it, these tests report the decoder's error as uncaught.
* fix(node): copy the multer fixes of platform-express again
The multer interceptors are copies of platform-express' (the file upload
parity spec checks it). Two fixes landed there since: a multipart request
with an unsupported content type is answered with a 415 (#18264), and
isRejectedByPipes() is no longer a named import from @nestjs/core/internal,
which made the package fail to load with a core older than 12.2 (#18251).
* fix(node): update multer to 2.5.0 and find-my-way to 9.10.0
As platform-express (#18268) and platform-fastify pin them. multer 2.5.0
fixes GHSA-q7qp-rjg7-q26m: a request aborted while an asynchronous
fileFilter is pending could crash the process.
* test(node): run master's new spec cases on the node adapter
The Node twins of the disconnect specs now wait for the producer teardown
as the Express and Fastify ones do since #18260, which fixes the same
off-by-one tick under load. getUrl() is checked for an https server
(#18252), and the specs of #18276 for middleware on routes that differ
only in their version run on the Node adapter too; both pass as they are.
* feat(node): add an option to trust proxies
Behind a reverse proxy, req.ip was always the proxy's address and
req.protocol "http" behind one that terminates TLS, so the throttler
counted every client as one, express-session would not set secure
cookies, and passport built http:// callback URLs. As Express' "trust
proxy" setting and Fastify's option of the same name, new NodeAdapter({
trustProxy }) takes true, a hop count, addresses or subnets, or a
function. For a request from a trusted proxy, req.ip, req.ips,
req.protocol, req.secure and req.hostname are read from the
X-Forwarded-* headers the way Express reads them, and
req.app.get('trust proxy') returns the setting. Unlike Fastify, which no
longer trusts a hop count, the adapter trusts it as Express does.
Without the option, the requests are NodeRequests as before: the getters
that read the headers belong to a subclass the option creates, so the
default requests run the same code. req.ips is new (empty there), and
req.protocol is typed as a string, as with Express.
* feat(node): add an option to parse the query string
The Node adapter parses query strings with fast-querystring into flat
keys, as Express and Fastify do by default, but offered no way to parse
nested objects and arrays, which Express gets from its "query parser"
setting and Fastify from its querystringParser option. As with Fastify,
new NodeAdapter({ querystringParser }) takes a function the query string
is passed to (without the "?", and "" when the URL has none), such as
str => qs.parse(str). Without it, requests run the same code as before.
* fix(node): trust no proxy for a hop count, as fastify does
A hop count cannot tell the socket's peer from a client that sends its
own X-Forwarded-For, so Fastify 5.12.1 and later trust no proxy for one,
and leave numbers out of the type of its trustProxy option. The Node
adapter now does the same, instead of trusting that many hops as Express
does. Addresses, subnets, true and functions are unchanged.
---------
Co-authored-by: Roman Khegay <rk@garuna.dev>
38 lines
826 B
TypeScript
38 lines
826 B
TypeScript
import type {
|
|
NodeBodyParserOptions,
|
|
NodeJsonParserOptions,
|
|
NodeTextParserOptions,
|
|
NodeUrlencodedParserOptions,
|
|
} from '../body-parser/body-parser.js';
|
|
|
|
/**
|
|
* Options of each body parser that `useBodyParser()` accepts.
|
|
*
|
|
* @publicApi
|
|
*/
|
|
export interface NestNodeBodyParserOptionsMap {
|
|
json: NodeJsonParserOptions;
|
|
urlencoded: NodeUrlencodedParserOptions;
|
|
text: NodeTextParserOptions;
|
|
raw: NodeBodyParserOptions;
|
|
}
|
|
|
|
/**
|
|
* @publicApi
|
|
*/
|
|
export type NestNodeBodyParserType = keyof NestNodeBodyParserOptionsMap;
|
|
|
|
/**
|
|
* @publicApi
|
|
*/
|
|
export type NestNodeBodyParserOptionsFor<
|
|
ParserType extends NestNodeBodyParserType,
|
|
> = Omit<NestNodeBodyParserOptionsMap[ParserType], 'verify'>;
|
|
|
|
export type {
|
|
NodeBodyParserOptions,
|
|
NodeJsonParserOptions,
|
|
NodeTextParserOptions,
|
|
NodeUrlencodedParserOptions,
|
|
};
|