@c9up/ream 0.1.25 → 0.1.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +65 -0
- package/dist/ConfigLoader.d.ts +46 -5
- package/dist/ConfigLoader.d.ts.map +1 -1
- package/dist/ConfigLoader.js +60 -9
- package/dist/ConfigLoader.js.map +1 -1
- package/dist/HttpKernel.d.ts.map +1 -1
- package/dist/HttpKernel.js +46 -6
- package/dist/HttpKernel.js.map +1 -1
- package/dist/Ignitor.d.ts +115 -7
- package/dist/Ignitor.d.ts.map +1 -1
- package/dist/Ignitor.js +254 -40
- package/dist/Ignitor.js.map +1 -1
- package/dist/console/BaseCommand.d.ts +217 -0
- package/dist/console/BaseCommand.d.ts.map +1 -0
- package/dist/console/BaseCommand.js +340 -0
- package/dist/console/BaseCommand.js.map +1 -0
- package/dist/console/Console.d.ts +86 -0
- package/dist/console/Console.d.ts.map +1 -0
- package/dist/console/Console.js +134 -0
- package/dist/console/Console.js.map +1 -0
- package/dist/console/ExceptionHandler.d.ts +28 -0
- package/dist/console/ExceptionHandler.d.ts.map +1 -0
- package/dist/console/ExceptionHandler.js +76 -0
- package/dist/console/ExceptionHandler.js.map +1 -0
- package/dist/console/HelpCommand.d.ts +16 -0
- package/dist/console/HelpCommand.d.ts.map +1 -0
- package/dist/console/HelpCommand.js +40 -0
- package/dist/console/HelpCommand.js.map +1 -0
- package/dist/console/IndexGenerator.d.ts +24 -0
- package/dist/console/IndexGenerator.d.ts.map +1 -0
- package/dist/console/IndexGenerator.js +65 -0
- package/dist/console/IndexGenerator.js.map +1 -0
- package/dist/console/Kernel.d.ts +298 -0
- package/dist/console/Kernel.d.ts.map +1 -0
- package/dist/console/Kernel.js +1120 -0
- package/dist/console/Kernel.js.map +1 -0
- package/dist/console/ListCommand.d.ts +18 -0
- package/dist/console/ListCommand.d.ts.map +1 -0
- package/dist/console/ListCommand.js +60 -0
- package/dist/console/ListCommand.js.map +1 -0
- package/dist/console/assertions.d.ts +20 -0
- package/dist/console/assertions.d.ts.map +1 -0
- package/dist/console/assertions.js +84 -0
- package/dist/console/assertions.js.map +1 -0
- package/dist/console/cliui.d.ts +248 -0
- package/dist/console/cliui.d.ts.map +1 -0
- package/dist/console/cliui.js +587 -0
- package/dist/console/cliui.js.map +1 -0
- package/dist/console/decorators.d.ts +90 -0
- package/dist/console/decorators.d.ts.map +1 -0
- package/dist/console/decorators.js +142 -0
- package/dist/console/decorators.js.map +1 -0
- package/dist/console/index.d.ts +32 -0
- package/dist/console/index.d.ts.map +1 -0
- package/dist/console/index.js +24 -0
- package/dist/console/index.js.map +1 -0
- package/dist/console/loaders.d.ts +52 -0
- package/dist/console/loaders.d.ts.map +1 -0
- package/dist/console/loaders.js +131 -0
- package/dist/console/loaders.js.map +1 -0
- package/dist/console/parser.d.ts +86 -0
- package/dist/console/parser.d.ts.map +1 -0
- package/dist/console/parser.js +440 -0
- package/dist/console/parser.js.map +1 -0
- package/dist/console/prompts.d.ts +124 -0
- package/dist/console/prompts.d.ts.map +1 -0
- package/dist/console/prompts.js +356 -0
- package/dist/console/prompts.js.map +1 -0
- package/dist/console/tracing.d.ts +17 -0
- package/dist/console/tracing.d.ts.map +1 -0
- package/dist/console/tracing.js +11 -0
- package/dist/console/tracing.js.map +1 -0
- package/dist/console/types.d.ts +255 -0
- package/dist/console/types.d.ts.map +1 -0
- package/dist/console/types.js +25 -0
- package/dist/console/types.js.map +1 -0
- package/dist/console/ui.d.ts +20 -0
- package/dist/console/ui.d.ts.map +1 -0
- package/dist/console/ui.js +31 -0
- package/dist/console/ui.js.map +1 -0
- package/dist/console/utils.d.ts +27 -0
- package/dist/console/utils.d.ts.map +1 -0
- package/dist/console/utils.js +56 -0
- package/dist/console/utils.js.map +1 -0
- package/dist/container/Container.d.ts +23 -3
- package/dist/container/Container.d.ts.map +1 -1
- package/dist/container/Container.js +177 -70
- package/dist/container/Container.js.map +1 -1
- package/dist/container/types.d.ts +14 -2
- package/dist/container/types.d.ts.map +1 -1
- package/dist/decorators/Service.d.ts +7 -0
- package/dist/decorators/Service.d.ts.map +1 -1
- package/dist/decorators/Service.js +23 -3
- package/dist/decorators/Service.js.map +1 -1
- package/dist/env/Env.d.ts +29 -4
- package/dist/env/Env.d.ts.map +1 -1
- package/dist/env/Env.js +27 -4
- package/dist/env/Env.js.map +1 -1
- package/dist/env/Secret.d.ts +11 -0
- package/dist/env/Secret.d.ts.map +1 -0
- package/dist/env/Secret.js +36 -0
- package/dist/env/Secret.js.map +1 -0
- package/dist/env/interpolate.d.ts +26 -0
- package/dist/env/interpolate.d.ts.map +1 -0
- package/dist/env/interpolate.js +48 -0
- package/dist/env/interpolate.js.map +1 -0
- package/dist/env/loadEnvFiles.d.ts.map +1 -1
- package/dist/env/loadEnvFiles.js +14 -4
- package/dist/env/loadEnvFiles.js.map +1 -1
- package/dist/env/schema.d.ts +23 -6
- package/dist/env/schema.d.ts.map +1 -1
- package/dist/env/schema.js +67 -33
- package/dist/env/schema.js.map +1 -1
- package/dist/errors/ReamError.d.ts +25 -0
- package/dist/errors/ReamError.d.ts.map +1 -1
- package/dist/errors/ReamError.js +5 -0
- package/dist/errors/ReamError.js.map +1 -1
- package/dist/errors/prettyPrintError.d.ts +9 -0
- package/dist/errors/prettyPrintError.d.ts.map +1 -0
- package/dist/errors/prettyPrintError.js +22 -0
- package/dist/errors/prettyPrintError.js.map +1 -0
- package/dist/events/Emitter.d.ts +1 -1
- package/dist/events/Emitter.d.ts.map +1 -1
- package/dist/events/Emitter.js +1 -1
- package/dist/events/Emitter.js.map +1 -1
- package/dist/events/EventsProvider.d.ts +2 -2
- package/dist/events/EventsProvider.d.ts.map +1 -1
- package/dist/events/EventsProvider.js +3 -3
- package/dist/events/EventsProvider.js.map +1 -1
- package/dist/graphql/GraphQLEngine.d.ts +1 -1
- package/dist/graphql/GraphQLEngine.d.ts.map +1 -1
- package/dist/graphql/GraphQLEngine.js +2 -2
- package/dist/graphql/GraphQLEngine.js.map +1 -1
- package/dist/graphql/GraphQLProvider.d.ts.map +1 -1
- package/dist/graphql/GraphQLProvider.js +7 -3
- package/dist/graphql/GraphQLProvider.js.map +1 -1
- package/dist/http/Exception.d.ts +63 -1
- package/dist/http/Exception.d.ts.map +1 -1
- package/dist/http/Exception.js +185 -48
- package/dist/http/Exception.js.map +1 -1
- package/dist/http/HttpContext.d.ts +53 -7
- package/dist/http/HttpContext.d.ts.map +1 -1
- package/dist/http/HttpContext.js +56 -15
- package/dist/http/HttpContext.js.map +1 -1
- package/dist/http/RedirectBuilder.d.ts.map +1 -1
- package/dist/http/RedirectBuilder.js +4 -1
- package/dist/http/RedirectBuilder.js.map +1 -1
- package/dist/http/Request.d.ts +141 -10
- package/dist/http/Request.d.ts.map +1 -1
- package/dist/http/Request.js +244 -34
- package/dist/http/Request.js.map +1 -1
- package/dist/http/Response.d.ts +176 -9
- package/dist/http/Response.d.ts.map +1 -1
- package/dist/http/Response.js +404 -16
- package/dist/http/Response.js.map +1 -1
- package/dist/index.d.ts +19 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -5
- package/dist/index.js.map +1 -1
- package/dist/middleware/Pipeline.d.ts +29 -8
- package/dist/middleware/Pipeline.d.ts.map +1 -1
- package/dist/middleware/Pipeline.js +40 -2
- package/dist/middleware/Pipeline.js.map +1 -1
- package/dist/openapi/OpenApiProvider.js +4 -4
- package/dist/openapi/OpenApiProvider.js.map +1 -1
- package/dist/router/Router.d.ts +223 -31
- package/dist/router/Router.d.ts.map +1 -1
- package/dist/router/Router.js +520 -102
- package/dist/router/Router.js.map +1 -1
- package/dist/rpc/RpcProvider.d.ts +1 -0
- package/dist/rpc/RpcProvider.d.ts.map +1 -1
- package/dist/rpc/RpcProvider.js +7 -3
- package/dist/rpc/RpcProvider.js.map +1 -1
- package/dist/rpc/RpcRouter.d.ts +2 -2
- package/dist/rpc/RpcRouter.d.ts.map +1 -1
- package/dist/rpc/RpcRouter.js +17 -5
- package/dist/rpc/RpcRouter.js.map +1 -1
- package/dist/scheduler/ScheduleProvider.d.ts.map +1 -1
- package/dist/scheduler/ScheduleProvider.js +7 -15
- package/dist/scheduler/ScheduleProvider.js.map +1 -1
- package/dist/server/Server.d.ts +17 -4
- package/dist/server/Server.d.ts.map +1 -1
- package/dist/server/Server.js +41 -7
- package/dist/server/Server.js.map +1 -1
- package/dist/services/app.d.ts +1 -1
- package/dist/services/app.js +1 -1
- package/dist/services/console.d.ts +21 -0
- package/dist/services/console.d.ts.map +1 -0
- package/dist/services/console.js +35 -0
- package/dist/services/console.js.map +1 -0
- package/dist/session/SessionMiddleware.js +3 -3
- package/dist/session/SessionMiddleware.js.map +1 -1
- package/dist/storage/StaticProvider.js +1 -1
- package/dist/storage/StaticProvider.js.map +1 -1
- package/dist/testing/ApiResponse.d.ts +218 -0
- package/dist/testing/ApiResponse.d.ts.map +1 -0
- package/dist/testing/ApiResponse.js +576 -0
- package/dist/testing/ApiResponse.js.map +1 -0
- package/dist/testing/RequestBuilder.d.ts +155 -35
- package/dist/testing/RequestBuilder.d.ts.map +1 -1
- package/dist/testing/RequestBuilder.js +455 -109
- package/dist/testing/RequestBuilder.js.map +1 -1
- package/dist/testing/TestClient.d.ts +53 -37
- package/dist/testing/TestClient.d.ts.map +1 -1
- package/dist/testing/TestClient.js +84 -52
- package/dist/testing/TestClient.js.map +1 -1
- package/dist/utils/Macroable.d.ts +30 -0
- package/dist/utils/Macroable.d.ts.map +1 -0
- package/dist/utils/Macroable.js +43 -0
- package/dist/utils/Macroable.js.map +1 -0
- package/dist/utils/inflect.d.ts +17 -0
- package/dist/utils/inflect.d.ts.map +1 -0
- package/dist/utils/inflect.js +32 -0
- package/dist/utils/inflect.js.map +1 -0
- package/dist/utils/objectPath.d.ts +57 -0
- package/dist/utils/objectPath.d.ts.map +1 -0
- package/dist/utils/objectPath.js +141 -0
- package/dist/utils/objectPath.js.map +1 -0
- package/events.darwin-arm64.node +0 -0
- package/events.darwin-x64.node +0 -0
- package/events.linux-arm64-gnu.node +0 -0
- package/events.linux-x64-gnu.node +0 -0
- package/events.win32-x64-msvc.node +0 -0
- package/index.darwin-arm64.node +0 -0
- package/index.darwin-x64.node +0 -0
- package/index.linux-arm64-gnu.node +0 -0
- package/index.linux-x64-gnu.node +0 -0
- package/index.win32-x64-msvc.node +0 -0
- package/package.json +20 -2
- package/scheduler.darwin-arm64.node +0 -0
- package/scheduler.darwin-x64.node +0 -0
- package/scheduler.linux-arm64-gnu.node +0 -0
- package/scheduler.linux-x64-gnu.node +0 -0
- package/scheduler.win32-x64-msvc.node +0 -0
- package/src/ConfigLoader.ts +72 -9
- package/src/HttpKernel.ts +53 -15
- package/src/Ignitor.ts +364 -45
- package/src/console/BaseCommand.ts +467 -0
- package/src/console/Console.ts +174 -0
- package/src/console/ExceptionHandler.ts +91 -0
- package/src/console/HelpCommand.ts +37 -0
- package/src/console/IndexGenerator.ts +79 -0
- package/src/console/Kernel.ts +1382 -0
- package/src/console/ListCommand.ts +55 -0
- package/src/console/assertions.ts +114 -0
- package/src/console/cliui.ts +756 -0
- package/src/console/decorators.ts +199 -0
- package/src/console/index.ts +67 -0
- package/src/console/loaders.ts +145 -0
- package/src/console/parser.ts +598 -0
- package/src/console/prompts.ts +548 -0
- package/src/console/tracing.ts +22 -0
- package/src/console/types.ts +280 -0
- package/src/console/ui.ts +37 -0
- package/src/console/utils.ts +69 -0
- package/src/container/Container.ts +198 -72
- package/src/container/types.ts +15 -2
- package/src/decorators/Service.ts +28 -3
- package/src/env/Env.ts +49 -5
- package/src/env/Secret.ts +41 -0
- package/src/env/interpolate.ts +54 -0
- package/src/env/loadEnvFiles.ts +12 -4
- package/src/env/schema.ts +109 -35
- package/src/errors/ReamError.ts +31 -0
- package/src/errors/prettyPrintError.ts +20 -0
- package/src/events/Emitter.ts +2 -2
- package/src/events/EventsProvider.ts +5 -5
- package/src/graphql/GraphQLEngine.ts +4 -4
- package/src/graphql/GraphQLProvider.ts +7 -3
- package/src/http/Exception.ts +214 -37
- package/src/http/HttpContext.ts +87 -18
- package/src/http/RedirectBuilder.ts +4 -1
- package/src/http/Request.ts +264 -34
- package/src/http/Response.ts +478 -27
- package/src/index.ts +41 -6
- package/src/middleware/Pipeline.ts +77 -6
- package/src/openapi/OpenApiProvider.ts +4 -4
- package/src/router/Router.ts +631 -113
- package/src/rpc/RpcProvider.ts +6 -2
- package/src/rpc/RpcRouter.ts +22 -7
- package/src/scheduler/ScheduleProvider.ts +7 -15
- package/src/server/Server.ts +49 -10
- package/src/services/app.ts +1 -1
- package/src/services/console.ts +42 -0
- package/src/session/SessionMiddleware.ts +4 -4
- package/src/storage/StaticProvider.ts +1 -1
- package/src/testing/ApiResponse.ts +691 -0
- package/src/testing/RequestBuilder.ts +577 -137
- package/src/testing/TestClient.ts +110 -77
- package/src/utils/Macroable.ts +54 -0
- package/src/utils/inflect.ts +29 -0
- package/src/utils/objectPath.ts +142 -0
- package/dist/console/CommandRunner.d.ts +0 -18
- package/dist/console/CommandRunner.d.ts.map +0 -1
- package/dist/console/CommandRunner.js +0 -65
- package/dist/console/CommandRunner.js.map +0 -1
- package/dist/decorators/Lazy.d.ts +0 -19
- package/dist/decorators/Lazy.d.ts.map +0 -1
- package/dist/decorators/Lazy.js +0 -53
- package/dist/decorators/Lazy.js.map +0 -1
- package/src/console/CommandRunner.ts +0 -82
- package/src/decorators/Lazy.ts +0 -57
|
@@ -9,7 +9,10 @@
|
|
|
9
9
|
* response.redirect().toRoute('posts.show', { id: '42' })
|
|
10
10
|
*/
|
|
11
11
|
function isSameOriginOrRelative(referer, requestUrl) {
|
|
12
|
-
|
|
12
|
+
// A relative path is trusted only when it starts with a single "/" and has no
|
|
13
|
+
// backslash: browsers normalise "\" to "/", so "/\evil.com" would become the
|
|
14
|
+
// protocol-relative "//evil.com" that a lone `!startsWith("//")` check misses.
|
|
15
|
+
if (referer.startsWith('/') && !referer.startsWith('//') && !referer.includes('\\'))
|
|
13
16
|
return true;
|
|
14
17
|
if (!requestUrl)
|
|
15
18
|
return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RedirectBuilder.js","sourceRoot":"","sources":["../../src/http/RedirectBuilder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,SAAS,sBAAsB,CAAC,OAAe,EAAE,UAAmB;IAClE,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"RedirectBuilder.js","sourceRoot":"","sources":["../../src/http/RedirectBuilder.ts"],"names":[],"mappings":"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"}
|
package/dist/http/Request.d.ts
CHANGED
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @implements FR21
|
|
8
8
|
*/
|
|
9
|
+
import type { CookieSigner } from '../security/CookieSigner.js';
|
|
10
|
+
import type { SignedUrl } from '../security/SignedUrl.js';
|
|
9
11
|
import type { Dict } from '../types/helpers.js';
|
|
12
|
+
import { Macroable } from '../utils/Macroable.js';
|
|
10
13
|
export interface RawRequest {
|
|
11
14
|
method: string;
|
|
12
15
|
path: string;
|
|
@@ -23,6 +26,12 @@ export interface RawRequest {
|
|
|
23
26
|
* `ip()` accessor falls back to legacy header parsing.
|
|
24
27
|
*/
|
|
25
28
|
ip?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Connection scheme as seen by the server (`http`/`https`), when the Rust
|
|
31
|
+
* layer ships it. Defaults to `http` in `protocol()` when absent; the
|
|
32
|
+
* `X-Forwarded-Proto` header only overrides it when trust-proxy is enabled.
|
|
33
|
+
*/
|
|
34
|
+
scheme?: 'http' | 'https';
|
|
26
35
|
/**
|
|
27
36
|
* Pre-parsed `multipart/form-data` payload — the HyperServer parses bodies
|
|
28
37
|
* server-side via `multer` and ships fields/files in this typed shape.
|
|
@@ -48,7 +57,7 @@ export interface RawRequest {
|
|
|
48
57
|
*/
|
|
49
58
|
cookies?: Dict;
|
|
50
59
|
}
|
|
51
|
-
export declare class Request {
|
|
60
|
+
export declare class Request extends Macroable {
|
|
52
61
|
#private;
|
|
53
62
|
/**
|
|
54
63
|
* CSRF token for this request (AdonisJS idiom: `request.csrfToken`). Seeded
|
|
@@ -56,9 +65,51 @@ export declare class Request {
|
|
|
56
65
|
* otherwise. Also published to `ctx.store` for templating helpers.
|
|
57
66
|
*/
|
|
58
67
|
csrfToken?: string;
|
|
68
|
+
/**
|
|
69
|
+
* `true` only when CSRF was enabled, the request method guarded, the route not
|
|
70
|
+
* excepted, AND the token validated for this request — set by the
|
|
71
|
+
* `@c9up/blackhole` middleware. Unlike {@link csrfToken} (seeded on every
|
|
72
|
+
* passing request, even when verification was skipped), this is the trustworthy
|
|
73
|
+
* "the request was CSRF-verified" signal a consumer reads to fail-close on
|
|
74
|
+
* state-changing routes. `undefined` when the middleware never ran.
|
|
75
|
+
*/
|
|
76
|
+
csrfProtected?: boolean;
|
|
59
77
|
constructor(raw: RawRequest, params?: Dict);
|
|
60
|
-
/**
|
|
78
|
+
/**
|
|
79
|
+
* The HTTP method, honouring `_method` form spoofing when enabled (AdonisJS
|
|
80
|
+
* `method`). With spoofing enabled and a real POST, the `_method` field
|
|
81
|
+
* (`PUT`/`PATCH`/`DELETE`) overrides — the classic HTML-form workaround.
|
|
82
|
+
* Spoofing is OFF by default (opt in via {@link setMethodSpoofing}); routing
|
|
83
|
+
* always uses {@link intended}.
|
|
84
|
+
*/
|
|
61
85
|
method(): string;
|
|
86
|
+
/** The real HTTP method, ignoring any `_method` spoofing (AdonisJS `intended`). */
|
|
87
|
+
intended(): string;
|
|
88
|
+
/** @internal Give the request access to its response — wired by HttpContext (for `fresh()`). */
|
|
89
|
+
setResponse(response: {
|
|
90
|
+
fresh(): boolean;
|
|
91
|
+
}): void;
|
|
92
|
+
/** @internal Record the matched route — wired by HttpContext (for `matchesRoute()`). */
|
|
93
|
+
setRouteInfo(info: {
|
|
94
|
+
name?: string;
|
|
95
|
+
pattern: string;
|
|
96
|
+
}): void;
|
|
97
|
+
/**
|
|
98
|
+
* Whether the client's cached copy is still fresh (AdonisJS `fresh`) —
|
|
99
|
+
* delegates to the response's `ETag`/`If-None-Match` revalidation check, so a
|
|
100
|
+
* handler can answer `304 Not Modified`. False before the response is wired.
|
|
101
|
+
*/
|
|
102
|
+
fresh(): boolean;
|
|
103
|
+
/** The negation of {@link fresh} (AdonisJS `stale`). */
|
|
104
|
+
stale(): boolean;
|
|
105
|
+
/** True when the matched route's name or pattern equals `identifier` (AdonisJS `matchesRoute`). */
|
|
106
|
+
matchesRoute(identifier: string): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Enable/disable `_method` form spoofing (AdonisJS gates this behind the
|
|
109
|
+
* `allowMethodSpoofing` config; ream exposes it as an explicit opt-in, off by
|
|
110
|
+
* default, so an attacker can never silently rewrite a POST into a DELETE).
|
|
111
|
+
*/
|
|
112
|
+
setMethodSpoofing(enabled: boolean): void;
|
|
62
113
|
/** Request URL (path + query string). */
|
|
63
114
|
url(includeQs?: boolean): string;
|
|
64
115
|
/** Request path (without query string). */
|
|
@@ -80,6 +131,41 @@ export declare class Request {
|
|
|
80
131
|
* desired resolved value.
|
|
81
132
|
*/
|
|
82
133
|
ip(): string;
|
|
134
|
+
/**
|
|
135
|
+
* Enable/disable trusting proxy headers (`X-Forwarded-Proto`/`-Host`/`-For`)
|
|
136
|
+
* for `protocol()`/`host()`/`ips()`. OFF by default — turning it on when the
|
|
137
|
+
* app is NOT behind a trusted proxy lets clients spoof their scheme/host/IP,
|
|
138
|
+
* so it's an explicit opt-in (same stance as {@link setMethodSpoofing}).
|
|
139
|
+
*/
|
|
140
|
+
setTrustProxy(enabled: boolean): void;
|
|
141
|
+
/**
|
|
142
|
+
* The request host including port (AdonisJS `host`). Honours
|
|
143
|
+
* `X-Forwarded-Host` ONLY when trust-proxy is enabled; otherwise the `Host`
|
|
144
|
+
* header. Returns null when neither is present.
|
|
145
|
+
*/
|
|
146
|
+
host(): string | null;
|
|
147
|
+
/**
|
|
148
|
+
* The request protocol — `http` or `https` (AdonisJS `protocol`). Honours
|
|
149
|
+
* `X-Forwarded-Proto` only under trust-proxy; otherwise the connection scheme
|
|
150
|
+
* the Rust layer reported (defaulting to `http`).
|
|
151
|
+
*/
|
|
152
|
+
protocol(): string;
|
|
153
|
+
/** True when the request protocol is `https` (AdonisJS `secure`). */
|
|
154
|
+
secure(): boolean;
|
|
155
|
+
/**
|
|
156
|
+
* The client IP chain (AdonisJS `ips`). Under trust-proxy, the parsed
|
|
157
|
+
* `X-Forwarded-For` list (left-most = original client); otherwise just the
|
|
158
|
+
* single resolved {@link ip}.
|
|
159
|
+
*/
|
|
160
|
+
ips(): string[];
|
|
161
|
+
/** The request hostname without port (AdonisJS `hostname`), or null. */
|
|
162
|
+
hostname(): string | null;
|
|
163
|
+
/**
|
|
164
|
+
* Subdomains of the hostname (AdonisJS `subdomains`). `offset` drops the
|
|
165
|
+
* registrable domain (default 2 → `example.com`); a leading `www` is removed.
|
|
166
|
+
* Empty for an IP host or a host with no subdomain.
|
|
167
|
+
*/
|
|
168
|
+
subdomains(offset?: number): string[];
|
|
83
169
|
/**
|
|
84
170
|
* Return all cookies sent on this request as a name → value map. The
|
|
85
171
|
* HyperServer parses the `Cookie:` header once via the `cookie` crate
|
|
@@ -88,14 +174,37 @@ export declare class Request {
|
|
|
88
174
|
* header — same tolerant `;`-split with quoted-value passthrough.
|
|
89
175
|
*/
|
|
90
176
|
cookies(): Dict;
|
|
91
|
-
/**
|
|
92
|
-
|
|
177
|
+
/** Inject the APP_KEY-backed cookie signer — wired by HttpContext. */
|
|
178
|
+
setCookieSigner(signer: CookieSigner): void;
|
|
179
|
+
/**
|
|
180
|
+
* Signed cookie value, verified with APP_KEY (AdonisJS default). Returns
|
|
181
|
+
* `defaultValue` (or null) when absent OR when the signature is invalid
|
|
182
|
+
* (tampered / not signed).
|
|
183
|
+
*/
|
|
184
|
+
cookie(name: string, defaultValue?: string): string | null;
|
|
185
|
+
/** Raw (unsigned) cookie value (AdonisJS `plainCookie`), or `defaultValue`/null when absent. */
|
|
186
|
+
plainCookie(name: string, defaultValue?: string): string | null;
|
|
187
|
+
/**
|
|
188
|
+
* Encrypted cookie value, decrypted with APP_KEY (AdonisJS `encryptedCookie`).
|
|
189
|
+
* Returns `defaultValue` (or null) when absent, undecryptable, or no
|
|
190
|
+
* encryption service.
|
|
191
|
+
*/
|
|
192
|
+
encryptedCookie(name: string, defaultValue?: string): string | null;
|
|
193
|
+
/** @internal Inject the APP_KEY-backed signed-URL helper — wired by HttpContext. */
|
|
194
|
+
setSignedUrl(signedUrl: SignedUrl): void;
|
|
195
|
+
/**
|
|
196
|
+
* Verify the request's signed-URL `signature` (AdonisJS `hasValidSignature`).
|
|
197
|
+
* Delegates to the {@link SignedUrl} helper, which recomputes the HMAC over
|
|
198
|
+
* the current path + query, rejects an expired `expires`, and checks the
|
|
199
|
+
* `purpose`. Returns false without an APP_KEY-backed signer.
|
|
200
|
+
*/
|
|
201
|
+
hasValidSignature(purpose?: string): boolean;
|
|
93
202
|
/** Get the raw body as a string (decoded from base64 if binary). */
|
|
94
203
|
raw(): string;
|
|
95
204
|
/** Get the raw body as a Buffer (preserves binary integrity for file uploads). */
|
|
96
205
|
rawBuffer(): Buffer;
|
|
97
|
-
/** Get a single request header (case-insensitive). */
|
|
98
|
-
header(key: string): string | undefined;
|
|
206
|
+
/** Get a single request header (case-insensitive), or `defaultValue` when absent. */
|
|
207
|
+
header(key: string, defaultValue?: string): string | undefined;
|
|
99
208
|
/** Get all request headers. */
|
|
100
209
|
headers(): Readonly<Dict>;
|
|
101
210
|
/** Get a single route parameter. */
|
|
@@ -106,14 +215,36 @@ export declare class Request {
|
|
|
106
215
|
qs(): Dict<unknown>;
|
|
107
216
|
/** Get the parsed request body. */
|
|
108
217
|
body(): unknown;
|
|
109
|
-
/**
|
|
218
|
+
/**
|
|
219
|
+
* Get a single input value from body or query string, by AdonisJS
|
|
220
|
+
* dot-notation (`input('user.address.city')`). Returns `defaultValue` when
|
|
221
|
+
* the path is absent (parity with `lodash.get`, reimplemented dependency-free).
|
|
222
|
+
*/
|
|
110
223
|
input<T = unknown>(key: string, defaultValue?: T): T;
|
|
111
224
|
/** Get all input (query string merged with body). */
|
|
112
225
|
all(): Dict<unknown>;
|
|
113
|
-
/**
|
|
114
|
-
|
|
115
|
-
|
|
226
|
+
/**
|
|
227
|
+
* The original request input, captured once and never mutated (AdonisJS
|
|
228
|
+
* `request.original`) — the basis for flash "old input" on validation errors.
|
|
229
|
+
*/
|
|
230
|
+
original(): Dict<unknown>;
|
|
231
|
+
/**
|
|
232
|
+
* Cherry-pick specific keys from input, honouring dot-notation for nested
|
|
233
|
+
* branches (`only(['user.id'])` → `{ user: { id } }`) — AdonisJS `only`
|
|
234
|
+
* (`lodash.pick`). Absent paths are skipped.
|
|
235
|
+
*/
|
|
236
|
+
only(keys: string[]): Dict<unknown>;
|
|
237
|
+
/**
|
|
238
|
+
* Get all input except specific keys, honouring dot-notation for nested
|
|
239
|
+
* branches — AdonisJS `except` (`lodash.omit`). Never mutates the input.
|
|
240
|
+
*/
|
|
116
241
|
except(keys: string[]): Dict<unknown>;
|
|
242
|
+
/**
|
|
243
|
+
* True when the request carries a body — a `content-length` above zero or a
|
|
244
|
+
* `transfer-encoding` header (AdonisJS `request.hasBody`). Lets a handler
|
|
245
|
+
* branch on "was anything sent" without parsing.
|
|
246
|
+
*/
|
|
247
|
+
hasBody(): boolean;
|
|
117
248
|
/** Check if the request content-type matches any of the given types. */
|
|
118
249
|
is(types: string[]): string | null;
|
|
119
250
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Request.d.ts","sourceRoot":"","sources":["../../src/http/Request.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"Request.d.ts","sourceRoot":"","sources":["../../src/http/Request.ts"],"names":[],"mappings":"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"}
|
package/dist/http/Request.js
CHANGED
|
@@ -6,12 +6,21 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @implements FR21
|
|
8
8
|
*/
|
|
9
|
-
|
|
9
|
+
import { Macroable } from '../utils/Macroable.js';
|
|
10
|
+
import { getPath, omitPaths, pickPaths } from '../utils/objectPath.js';
|
|
11
|
+
export class Request extends Macroable {
|
|
10
12
|
#raw;
|
|
11
13
|
#params;
|
|
14
|
+
#cookieSigner;
|
|
15
|
+
#signedUrl;
|
|
16
|
+
#allowMethodSpoofing = false;
|
|
17
|
+
#trustProxy = false;
|
|
18
|
+
#routeInfo;
|
|
19
|
+
#response;
|
|
12
20
|
#parsedBody;
|
|
13
21
|
#parsedQs;
|
|
14
22
|
#merged;
|
|
23
|
+
#original;
|
|
15
24
|
#files = new Map();
|
|
16
25
|
#validated;
|
|
17
26
|
/**
|
|
@@ -20,15 +29,74 @@ export class Request {
|
|
|
20
29
|
* otherwise. Also published to `ctx.store` for templating helpers.
|
|
21
30
|
*/
|
|
22
31
|
csrfToken;
|
|
32
|
+
/**
|
|
33
|
+
* `true` only when CSRF was enabled, the request method guarded, the route not
|
|
34
|
+
* excepted, AND the token validated for this request — set by the
|
|
35
|
+
* `@c9up/blackhole` middleware. Unlike {@link csrfToken} (seeded on every
|
|
36
|
+
* passing request, even when verification was skipped), this is the trustworthy
|
|
37
|
+
* "the request was CSRF-verified" signal a consumer reads to fail-close on
|
|
38
|
+
* state-changing routes. `undefined` when the middleware never ran.
|
|
39
|
+
*/
|
|
40
|
+
csrfProtected;
|
|
23
41
|
constructor(raw, params = {}) {
|
|
42
|
+
super();
|
|
24
43
|
this.#raw = raw;
|
|
25
44
|
this.#params = params;
|
|
26
45
|
}
|
|
27
46
|
// ─── HTTP accessors ───────────────────────────────────────
|
|
28
|
-
/**
|
|
47
|
+
/**
|
|
48
|
+
* The HTTP method, honouring `_method` form spoofing when enabled (AdonisJS
|
|
49
|
+
* `method`). With spoofing enabled and a real POST, the `_method` field
|
|
50
|
+
* (`PUT`/`PATCH`/`DELETE`) overrides — the classic HTML-form workaround.
|
|
51
|
+
* Spoofing is OFF by default (opt in via {@link setMethodSpoofing}); routing
|
|
52
|
+
* always uses {@link intended}.
|
|
53
|
+
*/
|
|
29
54
|
method() {
|
|
55
|
+
if (this.#allowMethodSpoofing && this.intended().toUpperCase() === 'POST') {
|
|
56
|
+
const spoofed = this.input('_method', this.intended());
|
|
57
|
+
if (typeof spoofed === 'string' && spoofed)
|
|
58
|
+
return spoofed.toUpperCase();
|
|
59
|
+
}
|
|
60
|
+
return this.intended();
|
|
61
|
+
}
|
|
62
|
+
/** The real HTTP method, ignoring any `_method` spoofing (AdonisJS `intended`). */
|
|
63
|
+
intended() {
|
|
30
64
|
return this.#raw.method;
|
|
31
65
|
}
|
|
66
|
+
/** @internal Give the request access to its response — wired by HttpContext (for `fresh()`). */
|
|
67
|
+
setResponse(response) {
|
|
68
|
+
this.#response = response;
|
|
69
|
+
}
|
|
70
|
+
/** @internal Record the matched route — wired by HttpContext (for `matchesRoute()`). */
|
|
71
|
+
setRouteInfo(info) {
|
|
72
|
+
this.#routeInfo = info;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Whether the client's cached copy is still fresh (AdonisJS `fresh`) —
|
|
76
|
+
* delegates to the response's `ETag`/`If-None-Match` revalidation check, so a
|
|
77
|
+
* handler can answer `304 Not Modified`. False before the response is wired.
|
|
78
|
+
*/
|
|
79
|
+
fresh() {
|
|
80
|
+
return this.#response?.fresh() ?? false;
|
|
81
|
+
}
|
|
82
|
+
/** The negation of {@link fresh} (AdonisJS `stale`). */
|
|
83
|
+
stale() {
|
|
84
|
+
return !this.fresh();
|
|
85
|
+
}
|
|
86
|
+
/** True when the matched route's name or pattern equals `identifier` (AdonisJS `matchesRoute`). */
|
|
87
|
+
matchesRoute(identifier) {
|
|
88
|
+
if (!this.#routeInfo)
|
|
89
|
+
return false;
|
|
90
|
+
return this.#routeInfo.name === identifier || this.#routeInfo.pattern === identifier;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Enable/disable `_method` form spoofing (AdonisJS gates this behind the
|
|
94
|
+
* `allowMethodSpoofing` config; ream exposes it as an explicit opt-in, off by
|
|
95
|
+
* default, so an attacker can never silently rewrite a POST into a DELETE).
|
|
96
|
+
*/
|
|
97
|
+
setMethodSpoofing(enabled) {
|
|
98
|
+
this.#allowMethodSpoofing = enabled;
|
|
99
|
+
}
|
|
32
100
|
/** Request URL (path + query string). */
|
|
33
101
|
url(includeQs = true) {
|
|
34
102
|
if (includeQs && this.#raw.query) {
|
|
@@ -61,6 +129,87 @@ export class Request {
|
|
|
61
129
|
return this.#raw.ip;
|
|
62
130
|
return this.#raw.remoteAddr ?? '127.0.0.1';
|
|
63
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* Enable/disable trusting proxy headers (`X-Forwarded-Proto`/`-Host`/`-For`)
|
|
134
|
+
* for `protocol()`/`host()`/`ips()`. OFF by default — turning it on when the
|
|
135
|
+
* app is NOT behind a trusted proxy lets clients spoof their scheme/host/IP,
|
|
136
|
+
* so it's an explicit opt-in (same stance as {@link setMethodSpoofing}).
|
|
137
|
+
*/
|
|
138
|
+
setTrustProxy(enabled) {
|
|
139
|
+
this.#trustProxy = enabled;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* The request host including port (AdonisJS `host`). Honours
|
|
143
|
+
* `X-Forwarded-Host` ONLY when trust-proxy is enabled; otherwise the `Host`
|
|
144
|
+
* header. Returns null when neither is present.
|
|
145
|
+
*/
|
|
146
|
+
host() {
|
|
147
|
+
if (this.#trustProxy) {
|
|
148
|
+
const forwarded = this.#raw.headers['x-forwarded-host'];
|
|
149
|
+
if (forwarded)
|
|
150
|
+
return forwarded.split(',')[0].trim();
|
|
151
|
+
}
|
|
152
|
+
return this.#raw.headers.host ?? null;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* The request protocol — `http` or `https` (AdonisJS `protocol`). Honours
|
|
156
|
+
* `X-Forwarded-Proto` only under trust-proxy; otherwise the connection scheme
|
|
157
|
+
* the Rust layer reported (defaulting to `http`).
|
|
158
|
+
*/
|
|
159
|
+
protocol() {
|
|
160
|
+
if (this.#trustProxy) {
|
|
161
|
+
const forwarded = this.#raw.headers['x-forwarded-proto'];
|
|
162
|
+
if (forwarded)
|
|
163
|
+
return forwarded.split(',')[0].trim().toLowerCase();
|
|
164
|
+
}
|
|
165
|
+
return this.#raw.scheme ?? 'http';
|
|
166
|
+
}
|
|
167
|
+
/** True when the request protocol is `https` (AdonisJS `secure`). */
|
|
168
|
+
secure() {
|
|
169
|
+
return this.protocol() === 'https';
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* The client IP chain (AdonisJS `ips`). Under trust-proxy, the parsed
|
|
173
|
+
* `X-Forwarded-For` list (left-most = original client); otherwise just the
|
|
174
|
+
* single resolved {@link ip}.
|
|
175
|
+
*/
|
|
176
|
+
ips() {
|
|
177
|
+
if (this.#trustProxy) {
|
|
178
|
+
const forwarded = this.#raw.headers['x-forwarded-for'];
|
|
179
|
+
if (forwarded) {
|
|
180
|
+
return forwarded
|
|
181
|
+
.split(',')
|
|
182
|
+
.map((value) => value.trim())
|
|
183
|
+
.filter((value) => value.length > 0);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return [this.ip()];
|
|
187
|
+
}
|
|
188
|
+
/** The request hostname without port (AdonisJS `hostname`), or null. */
|
|
189
|
+
hostname() {
|
|
190
|
+
const host = this.host();
|
|
191
|
+
if (host === null)
|
|
192
|
+
return null;
|
|
193
|
+
// Strip the port. IPv6 literals are bracketed (`[::1]:3000`) — keep the brackets' contents.
|
|
194
|
+
if (host.startsWith('['))
|
|
195
|
+
return host.slice(0, host.indexOf(']') + 1) || host;
|
|
196
|
+
const colon = host.indexOf(':');
|
|
197
|
+
return colon === -1 ? host : host.slice(0, colon);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Subdomains of the hostname (AdonisJS `subdomains`). `offset` drops the
|
|
201
|
+
* registrable domain (default 2 → `example.com`); a leading `www` is removed.
|
|
202
|
+
* Empty for an IP host or a host with no subdomain.
|
|
203
|
+
*/
|
|
204
|
+
subdomains(offset = 2) {
|
|
205
|
+
const hostname = this.hostname();
|
|
206
|
+
if (hostname === null || isIpLiteral(hostname))
|
|
207
|
+
return [];
|
|
208
|
+
const parts = hostname.split('.').reverse().slice(offset);
|
|
209
|
+
if (parts.length > 0 && parts[parts.length - 1] === 'www')
|
|
210
|
+
parts.pop();
|
|
211
|
+
return parts;
|
|
212
|
+
}
|
|
64
213
|
/**
|
|
65
214
|
* Return all cookies sent on this request as a name → value map. The
|
|
66
215
|
* HyperServer parses the `Cookie:` header once via the `cookie` crate
|
|
@@ -93,10 +242,49 @@ export class Request {
|
|
|
93
242
|
}
|
|
94
243
|
return result;
|
|
95
244
|
}
|
|
96
|
-
/**
|
|
97
|
-
|
|
245
|
+
/** Inject the APP_KEY-backed cookie signer — wired by HttpContext. */
|
|
246
|
+
setCookieSigner(signer) {
|
|
247
|
+
this.#cookieSigner = signer;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Signed cookie value, verified with APP_KEY (AdonisJS default). Returns
|
|
251
|
+
* `defaultValue` (or null) when absent OR when the signature is invalid
|
|
252
|
+
* (tampered / not signed).
|
|
253
|
+
*/
|
|
254
|
+
cookie(name, defaultValue) {
|
|
255
|
+
const raw = this.plainCookie(name);
|
|
256
|
+
const value = raw === null ? null : this.#cookieSigner ? this.#cookieSigner.unsign(raw) : raw;
|
|
257
|
+
return value ?? defaultValue ?? null;
|
|
258
|
+
}
|
|
259
|
+
/** Raw (unsigned) cookie value (AdonisJS `plainCookie`), or `defaultValue`/null when absent. */
|
|
260
|
+
plainCookie(name, defaultValue) {
|
|
98
261
|
const cookies = this.#raw.cookies ?? this.cookies();
|
|
99
|
-
return cookies[name] ?? null;
|
|
262
|
+
return cookies[name] ?? defaultValue ?? null;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Encrypted cookie value, decrypted with APP_KEY (AdonisJS `encryptedCookie`).
|
|
266
|
+
* Returns `defaultValue` (or null) when absent, undecryptable, or no
|
|
267
|
+
* encryption service.
|
|
268
|
+
*/
|
|
269
|
+
encryptedCookie(name, defaultValue) {
|
|
270
|
+
const raw = this.plainCookie(name);
|
|
271
|
+
const value = raw === null || !this.#cookieSigner ? null : this.#cookieSigner.decrypt(raw);
|
|
272
|
+
return value ?? defaultValue ?? null;
|
|
273
|
+
}
|
|
274
|
+
/** @internal Inject the APP_KEY-backed signed-URL helper — wired by HttpContext. */
|
|
275
|
+
setSignedUrl(signedUrl) {
|
|
276
|
+
this.#signedUrl = signedUrl;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Verify the request's signed-URL `signature` (AdonisJS `hasValidSignature`).
|
|
280
|
+
* Delegates to the {@link SignedUrl} helper, which recomputes the HMAC over
|
|
281
|
+
* the current path + query, rejects an expired `expires`, and checks the
|
|
282
|
+
* `purpose`. Returns false without an APP_KEY-backed signer.
|
|
283
|
+
*/
|
|
284
|
+
hasValidSignature(purpose) {
|
|
285
|
+
if (!this.#signedUrl)
|
|
286
|
+
return false;
|
|
287
|
+
return this.#signedUrl.verify(this.url(), purpose);
|
|
100
288
|
}
|
|
101
289
|
/** Get the raw body as a string (decoded from base64 if binary). */
|
|
102
290
|
raw() {
|
|
@@ -113,9 +301,9 @@ export class Request {
|
|
|
113
301
|
return Buffer.from(this.#raw.body, 'utf8');
|
|
114
302
|
}
|
|
115
303
|
// ─── Headers ──────────────────────────────────────────────
|
|
116
|
-
/** Get a single request header (case-insensitive). */
|
|
117
|
-
header(key) {
|
|
118
|
-
return this.#raw.headers[key.toLowerCase()];
|
|
304
|
+
/** Get a single request header (case-insensitive), or `defaultValue` when absent. */
|
|
305
|
+
header(key, defaultValue) {
|
|
306
|
+
return this.#raw.headers[key.toLowerCase()] ?? defaultValue;
|
|
119
307
|
}
|
|
120
308
|
/** Get all request headers. */
|
|
121
309
|
headers() {
|
|
@@ -145,45 +333,61 @@ export class Request {
|
|
|
145
333
|
return this.#parsedBody;
|
|
146
334
|
}
|
|
147
335
|
// ─── Merged input (body + qs) ─────────────────────────────
|
|
148
|
-
/**
|
|
336
|
+
/**
|
|
337
|
+
* Get a single input value from body or query string, by AdonisJS
|
|
338
|
+
* dot-notation (`input('user.address.city')`). Returns `defaultValue` when
|
|
339
|
+
* the path is absent (parity with `lodash.get`, reimplemented dependency-free).
|
|
340
|
+
*/
|
|
149
341
|
input(key, defaultValue) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
return merged[key];
|
|
154
|
-
}
|
|
155
|
-
// biome-ignore lint/suspicious/noExplicitAny: generic default — caller brands the value type via T
|
|
156
|
-
return defaultValue;
|
|
342
|
+
// Untyped request data: the caller declares the shape it expects (same
|
|
343
|
+
// contract as AdonisJS `request.input<T>`, whose return is loose `any`).
|
|
344
|
+
return getPath(this.all(), key, defaultValue);
|
|
157
345
|
}
|
|
158
346
|
/** Get all input (query string merged with body). */
|
|
159
347
|
all() {
|
|
160
348
|
if (!this.#merged) {
|
|
161
349
|
this.#ensureParsedBody();
|
|
162
350
|
this.#merged = { ...this.qs(), ...this.#parsedBody };
|
|
351
|
+
// Snapshot the first-seen input as the immutable "original" (flash old-input).
|
|
352
|
+
if (this.#original === undefined)
|
|
353
|
+
this.#original = { ...this.#merged };
|
|
163
354
|
}
|
|
164
355
|
return { ...this.#merged };
|
|
165
356
|
}
|
|
166
|
-
/**
|
|
357
|
+
/**
|
|
358
|
+
* The original request input, captured once and never mutated (AdonisJS
|
|
359
|
+
* `request.original`) — the basis for flash "old input" on validation errors.
|
|
360
|
+
*/
|
|
361
|
+
original() {
|
|
362
|
+
this.all(); // ensure the snapshot is captured
|
|
363
|
+
return { ...(this.#original ?? {}) };
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Cherry-pick specific keys from input, honouring dot-notation for nested
|
|
367
|
+
* branches (`only(['user.id'])` → `{ user: { id } }`) — AdonisJS `only`
|
|
368
|
+
* (`lodash.pick`). Absent paths are skipped.
|
|
369
|
+
*/
|
|
167
370
|
only(keys) {
|
|
168
|
-
|
|
169
|
-
const result = {};
|
|
170
|
-
for (const key of keys) {
|
|
171
|
-
if (key in merged) {
|
|
172
|
-
result[key] = merged[key];
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
return result;
|
|
371
|
+
return pickPaths(this.all(), keys);
|
|
176
372
|
}
|
|
177
|
-
/**
|
|
373
|
+
/**
|
|
374
|
+
* Get all input except specific keys, honouring dot-notation for nested
|
|
375
|
+
* branches — AdonisJS `except` (`lodash.omit`). Never mutates the input.
|
|
376
|
+
*/
|
|
178
377
|
except(keys) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
378
|
+
return omitPaths(this.all(), keys);
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* True when the request carries a body — a `content-length` above zero or a
|
|
382
|
+
* `transfer-encoding` header (AdonisJS `request.hasBody`). Lets a handler
|
|
383
|
+
* branch on "was anything sent" without parsing.
|
|
384
|
+
*/
|
|
385
|
+
hasBody() {
|
|
386
|
+
const transferEncoding = this.#raw.headers['transfer-encoding'];
|
|
387
|
+
if (transferEncoding && transferEncoding.length > 0)
|
|
388
|
+
return true;
|
|
389
|
+
const contentLength = Number.parseInt(this.#raw.headers['content-length'] ?? '', 10);
|
|
390
|
+
return Number.isFinite(contentLength) && contentLength > 0;
|
|
187
391
|
}
|
|
188
392
|
// ─── Content negotiation ──────────────────────────────────
|
|
189
393
|
/** Check if the request content-type matches any of the given types. */
|
|
@@ -357,6 +561,12 @@ export class Request {
|
|
|
357
561
|
function isPlainObject(value) {
|
|
358
562
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
359
563
|
}
|
|
564
|
+
/** True for an IPv4 dotted-quad or a (bracketed) IPv6 literal — hosts with no subdomains. */
|
|
565
|
+
function isIpLiteral(host) {
|
|
566
|
+
if (host.startsWith('[') || host.includes('::'))
|
|
567
|
+
return true;
|
|
568
|
+
return /^(\d{1,3}\.){3}\d{1,3}$/.test(host);
|
|
569
|
+
}
|
|
360
570
|
/**
|
|
361
571
|
* Decode a percent-encoded segment without throwing on malformed input.
|
|
362
572
|
* Browsers happily send `q=%E0%A4%A` (truncated UTF-8 sequences) — refusing
|