@fluojs/http 1.1.2 → 3.0.0
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.ko.md +430 -15
- package/README.md +437 -15
- package/dist/access-log-observer.d.ts +77 -0
- package/dist/access-log-observer.d.ts.map +1 -0
- package/dist/access-log-observer.js +171 -0
- package/dist/adapter.d.ts +9 -0
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +15 -1
- package/dist/adapters/binding.d.ts.map +1 -1
- package/dist/adapters/binding.js +18 -16
- package/dist/adapters/dto-binding-plan.d.ts +2 -2
- package/dist/adapters/dto-binding-plan.d.ts.map +1 -1
- package/dist/adapters/dto-binding-plan.js +13 -4
- package/dist/adapters/dto-validation-adapter.d.ts +2 -1
- package/dist/adapters/dto-validation-adapter.d.ts.map +1 -1
- package/dist/adapters/dto-validation-adapter.js +2 -2
- package/dist/byte-range-response.d.ts +71 -0
- package/dist/byte-range-response.d.ts.map +1 -0
- package/dist/byte-range-response.js +347 -0
- package/dist/client-identity.d.ts +8 -4
- package/dist/client-identity.d.ts.map +1 -1
- package/dist/client-identity.js +12 -93
- package/dist/compiled-route-identity.d.ts +17 -0
- package/dist/compiled-route-identity.d.ts.map +1 -0
- package/dist/compiled-route-identity.js +29 -0
- package/dist/connection.d.ts +67 -0
- package/dist/connection.d.ts.map +1 -0
- package/dist/connection.js +480 -0
- package/dist/context/request-context-node-store.d.ts +6 -0
- package/dist/context/request-context-node-store.d.ts.map +1 -1
- package/dist/context/request-context-node-store.js +14 -0
- package/dist/context/request-context.d.ts +5 -5
- package/dist/context/request-context.d.ts.map +1 -1
- package/dist/context/request-context.js +8 -83
- package/dist/context/request-id.d.ts +10 -0
- package/dist/context/request-id.d.ts.map +1 -0
- package/dist/context/request-id.js +27 -0
- package/dist/context/sse.d.ts +13 -0
- package/dist/context/sse.d.ts.map +1 -1
- package/dist/context/sse.js +36 -6
- package/dist/cookie-helpers.d.ts +47 -0
- package/dist/cookie-helpers.d.ts.map +1 -0
- package/dist/cookie-helpers.js +166 -0
- package/dist/decorators.d.ts +52 -19
- package/dist/decorators.d.ts.map +1 -1
- package/dist/decorators.js +57 -10
- package/dist/dispatch/conditional-request-policy.d.ts +67 -0
- package/dist/dispatch/conditional-request-policy.d.ts.map +1 -0
- package/dist/dispatch/conditional-request-policy.js +297 -0
- package/dist/dispatch/dispatch-content-negotiation.d.ts +8 -0
- package/dist/dispatch/dispatch-content-negotiation.d.ts.map +1 -1
- package/dist/dispatch/dispatch-content-negotiation.js +89 -42
- package/dist/dispatch/dispatch-error-negotiation.d.ts +26 -0
- package/dist/dispatch/dispatch-error-negotiation.d.ts.map +1 -0
- package/dist/dispatch/dispatch-error-negotiation.js +110 -0
- package/dist/dispatch/dispatch-error-policy.d.ts +1 -10
- package/dist/dispatch/dispatch-error-policy.d.ts.map +1 -1
- package/dist/dispatch/dispatch-error-policy.js +1 -33
- package/dist/dispatch/dispatch-error-representation.d.ts +18 -0
- package/dist/dispatch/dispatch-error-representation.d.ts.map +1 -0
- package/dist/dispatch/dispatch-error-representation.js +125 -0
- package/dist/dispatch/dispatch-response-metadata.d.ts +10 -0
- package/dist/dispatch/dispatch-response-metadata.d.ts.map +1 -0
- package/dist/dispatch/dispatch-response-metadata.js +12 -0
- package/dist/dispatch/dispatch-response-policy.d.ts +33 -5
- package/dist/dispatch/dispatch-response-policy.d.ts.map +1 -1
- package/dist/dispatch/dispatch-response-policy.js +149 -18
- package/dist/dispatch/dispatcher.d.ts +5 -1
- package/dist/dispatch/dispatcher.d.ts.map +1 -1
- package/dist/dispatch/dispatcher.js +178 -107
- package/dist/dispatch/fast-path/debug-visibility.d.ts.map +1 -1
- package/dist/dispatch/fast-path/debug-visibility.js +6 -3
- package/dist/dispatch/fast-path/dispatcher-state.d.ts +10 -0
- package/dist/dispatch/fast-path/dispatcher-state.d.ts.map +1 -0
- package/dist/dispatch/fast-path/dispatcher-state.js +52 -0
- package/dist/dispatch/fast-path/eligibility-checker.d.ts.map +1 -1
- package/dist/dispatch/fast-path/eligibility-checker.js +27 -15
- package/dist/dispatch/fast-path/eligibility.d.ts +16 -10
- package/dist/dispatch/fast-path/eligibility.d.ts.map +1 -1
- package/dist/dispatch/fast-path/eligibility.js +10 -4
- package/dist/dispatch/fast-path/fast-path-executor.d.ts +14 -1
- package/dist/dispatch/fast-path/fast-path-executor.d.ts.map +1 -1
- package/dist/dispatch/fast-path/fast-path-executor.js +23 -6
- package/dist/dispatch/request-abort.d.ts +22 -0
- package/dist/dispatch/request-abort.d.ts.map +1 -0
- package/dist/dispatch/request-abort.js +30 -0
- package/dist/dispatch/response-integration.d.ts +55 -0
- package/dist/dispatch/response-integration.d.ts.map +1 -0
- package/dist/dispatch/response-integration.js +57 -0
- package/dist/errors.d.ts +10 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +19 -0
- package/dist/guards.d.ts +1 -1
- package/dist/guards.d.ts.map +1 -1
- package/dist/header-helpers.d.ts +59 -0
- package/dist/header-helpers.d.ts.map +1 -0
- package/dist/header-helpers.js +185 -0
- package/dist/index.d.ts +1 -16
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -15
- package/dist/index.portable.d.ts +25 -0
- package/dist/index.portable.d.ts.map +1 -0
- package/dist/index.portable.js +21 -0
- package/dist/internal.d.ts +3 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +2 -0
- package/dist/mapping.d.ts.map +1 -1
- package/dist/mapping.js +100 -15
- package/dist/middleware/correlation.d.ts +9 -1
- package/dist/middleware/correlation.d.ts.map +1 -1
- package/dist/middleware/correlation.js +25 -14
- package/dist/middleware/cors.d.ts.map +1 -1
- package/dist/middleware/cors.js +7 -8
- package/dist/middleware/middleware.d.ts +3 -3
- package/dist/middleware/middleware.d.ts.map +1 -1
- package/dist/middleware/rate-limit.d.ts +13 -2
- package/dist/middleware/rate-limit.d.ts.map +1 -1
- package/dist/middleware/rate-limit.js +1 -0
- package/dist/static-assets.d.ts +77 -0
- package/dist/static-assets.d.ts.map +1 -0
- package/dist/static-assets.js +270 -0
- package/dist/types.d.ts +225 -17
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +71 -1
- package/package.json +19 -9
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
function normalizeHeaderName(name) {
|
|
2
|
+
const normalized = name.trim().toLowerCase();
|
|
3
|
+
return normalized.length > 0 ? normalized : undefined;
|
|
4
|
+
}
|
|
5
|
+
function findCaseInsensitiveHeaderEntry(headers, headerName) {
|
|
6
|
+
const normalizedHeaderName = normalizeHeaderName(headerName);
|
|
7
|
+
if (!normalizedHeaderName) {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
let firstMatch;
|
|
11
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
12
|
+
if (name.toLowerCase() !== normalizedHeaderName) {
|
|
13
|
+
continue;
|
|
14
|
+
}
|
|
15
|
+
if (value !== undefined) {
|
|
16
|
+
return [name, value];
|
|
17
|
+
}
|
|
18
|
+
firstMatch ??= [name, value];
|
|
19
|
+
}
|
|
20
|
+
return firstMatch;
|
|
21
|
+
}
|
|
22
|
+
function parseHeaderTokens(values) {
|
|
23
|
+
const tokens = [];
|
|
24
|
+
for (const value of values) {
|
|
25
|
+
for (const token of value.split(',')) {
|
|
26
|
+
const normalized = token.trim();
|
|
27
|
+
if (normalized.length > 0) {
|
|
28
|
+
tokens.push(normalized);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return tokens;
|
|
33
|
+
}
|
|
34
|
+
function readJoinedNonEmptyHeaderValue(value) {
|
|
35
|
+
if (Array.isArray(value)) {
|
|
36
|
+
const normalizedValues = value.map(entry => entry.trim()).filter(entry => entry.length > 0);
|
|
37
|
+
return normalizedValues.length > 0 ? normalizedValues.join(',') : undefined;
|
|
38
|
+
}
|
|
39
|
+
const normalized = value?.trim();
|
|
40
|
+
return normalized ? normalized : undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Reads one request header without flattening multi-value arrays.
|
|
45
|
+
*
|
|
46
|
+
* @param request Adapter-normalized request carrying the inbound headers map.
|
|
47
|
+
* @param name Header name to resolve case-insensitively.
|
|
48
|
+
* @returns The original scalar, array, or `undefined` stored on the request.
|
|
49
|
+
*/
|
|
50
|
+
export function getRequestHeader(request, name) {
|
|
51
|
+
return findCaseInsensitiveHeaderEntry(request.headers, name)?.[1];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Reads one response header without flattening multi-value arrays.
|
|
56
|
+
*
|
|
57
|
+
* @param response Adapter-normalized response carrying the outbound headers map.
|
|
58
|
+
* @param name Header name to resolve case-insensitively.
|
|
59
|
+
* @returns The original scalar, array, or `undefined` stored on the response.
|
|
60
|
+
*/
|
|
61
|
+
export function getResponseHeader(response, name) {
|
|
62
|
+
return findCaseInsensitiveHeaderEntry(response.headers, name)?.[1];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Checks whether one response header is present without mutating the response.
|
|
67
|
+
*
|
|
68
|
+
* @param response Adapter-normalized response carrying the outbound headers map.
|
|
69
|
+
* @param name Header name to resolve case-insensitively.
|
|
70
|
+
* @returns `true` when a matching response header has a value.
|
|
71
|
+
*/
|
|
72
|
+
export function hasResponseHeader(response, name) {
|
|
73
|
+
return getResponseHeader(response, name) !== undefined;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Creates a portable Content-Disposition value with ASCII and UTF-8 filename parameters.
|
|
78
|
+
*
|
|
79
|
+
* @param disposition Whether the response is an `attachment` or rendered `inline`.
|
|
80
|
+
* @param filename Original filename to encode for a response header.
|
|
81
|
+
* @returns A Content-Disposition field value with escaped ASCII and RFC 8187 UTF-8 parameters.
|
|
82
|
+
* @throws {TypeError} When the disposition is unsupported or the filename contains CR or LF.
|
|
83
|
+
*/
|
|
84
|
+
export function buildContentDisposition(disposition, filename) {
|
|
85
|
+
if (disposition !== 'attachment' && disposition !== 'inline') {
|
|
86
|
+
throw new TypeError('Content-Disposition disposition must be attachment or inline.');
|
|
87
|
+
}
|
|
88
|
+
if (filename.includes('\r') || filename.includes('\n')) {
|
|
89
|
+
throw new TypeError('Content-Disposition filenames cannot contain CR or LF characters.');
|
|
90
|
+
}
|
|
91
|
+
const asciiFilename = filename.replace(/[^\x20-\x7E]/gu, '?').replaceAll('\\', '\\\\').replaceAll('"', '\\"');
|
|
92
|
+
const utf8Filename = Array.from(new TextEncoder().encode(filename), byte => {
|
|
93
|
+
const isAlphaNumeric = byte >= 0x30 && byte <= 0x39 || byte >= 0x41 && byte <= 0x5a || byte >= 0x61 && byte <= 0x7a;
|
|
94
|
+
const isRfc8187Punctuation = byte === 0x21 || byte === 0x23 || byte === 0x24 || byte === 0x26 || byte === 0x2b || byte === 0x2d || byte === 0x2e || byte === 0x5e || byte === 0x5f || byte === 0x60 || byte === 0x7c || byte === 0x7e;
|
|
95
|
+
return isAlphaNumeric || isRfc8187Punctuation ? String.fromCharCode(byte) : `%${byte.toString(16).toUpperCase().padStart(2, '0')}`;
|
|
96
|
+
}).join('');
|
|
97
|
+
return `${disposition}; filename="${asciiFilename}"; filename*=UTF-8''${utf8Filename}`;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Reads the first non-empty request header value across duplicate case variants.
|
|
102
|
+
*
|
|
103
|
+
* @param request Adapter-normalized request carrying the inbound headers map.
|
|
104
|
+
* @param name Header name to resolve case-insensitively.
|
|
105
|
+
* @returns The first trimmed scalar or joined array value that is not blank.
|
|
106
|
+
*/
|
|
107
|
+
export function readFirstNonEmptyRequestHeaderValue(request, name) {
|
|
108
|
+
const normalizedHeaderName = normalizeHeaderName(name);
|
|
109
|
+
if (!normalizedHeaderName) {
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
for (const [headerName, value] of Object.entries(request.headers)) {
|
|
113
|
+
if (headerName.toLowerCase() !== normalizedHeaderName) {
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const normalizedValue = readJoinedNonEmptyHeaderValue(value);
|
|
117
|
+
if (normalizedValue !== undefined) {
|
|
118
|
+
return normalizedValue;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Reads and joins every non-empty request header field value in wire order.
|
|
126
|
+
*
|
|
127
|
+
* @param request Adapter-normalized request carrying the inbound headers map.
|
|
128
|
+
* @param name Header name to resolve case-insensitively.
|
|
129
|
+
* @returns Comma-delimited values from every matching field, or `undefined` when all are blank.
|
|
130
|
+
*/
|
|
131
|
+
export function readJoinedNonEmptyRequestHeaderValues(request, name) {
|
|
132
|
+
const normalizedHeaderName = normalizeHeaderName(name);
|
|
133
|
+
if (!normalizedHeaderName) {
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
const values = [];
|
|
137
|
+
for (const [headerName, value] of Object.entries(request.headers)) {
|
|
138
|
+
if (headerName.toLowerCase() !== normalizedHeaderName) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
const normalizedValue = readJoinedNonEmptyHeaderValue(value);
|
|
142
|
+
if (normalizedValue !== undefined) {
|
|
143
|
+
values.push(normalizedValue);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return values.length > 0 ? values.join(',') : undefined;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Appends one or more fields to the response `Vary` header with case-insensitive deduplication.
|
|
151
|
+
*
|
|
152
|
+
* @param response Mutable framework response facade that owns the header map.
|
|
153
|
+
* @param fields Header field names or comma-delimited field lists to append.
|
|
154
|
+
* @returns Nothing. The helper updates the response header map in place when needed.
|
|
155
|
+
*/
|
|
156
|
+
export function appendVaryHeader(response, ...fields) {
|
|
157
|
+
const existingEntries = Object.entries(response.headers).filter(([name]) => name.toLowerCase() === 'vary');
|
|
158
|
+
const existingTokens = parseHeaderTokens(existingEntries.flatMap(([, value]) => Array.isArray(value) ? value : [value]));
|
|
159
|
+
const appendedTokens = parseHeaderTokens(fields);
|
|
160
|
+
const mergedTokens = [...existingTokens, ...appendedTokens];
|
|
161
|
+
if (mergedTokens.length === 0) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const canonicalHeaderName = existingEntries[0]?.[0] ?? 'Vary';
|
|
165
|
+
for (const [name] of existingEntries.slice(1)) {
|
|
166
|
+
delete response.headers[name];
|
|
167
|
+
}
|
|
168
|
+
if (mergedTokens.some(token => token === '*')) {
|
|
169
|
+
response.setHeader(canonicalHeaderName, '*');
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const dedupedTokens = [];
|
|
173
|
+
const seen = new Set();
|
|
174
|
+
for (const token of mergedTokens) {
|
|
175
|
+
const normalized = token.toLowerCase();
|
|
176
|
+
if (seen.has(normalized)) {
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
seen.add(normalized);
|
|
180
|
+
dedupedTokens.push(token);
|
|
181
|
+
}
|
|
182
|
+
if (dedupedTokens.length > 0) {
|
|
183
|
+
response.setHeader(canonicalHeaderName, dedupedTokens.join(', '));
|
|
184
|
+
}
|
|
185
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,17 +1,2 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './middleware/correlation.js';
|
|
3
|
-
export * from './middleware/cors.js';
|
|
4
|
-
export { All, Controller, Convert, Delete, FromBody, FromCookie, FromHeader, FromPath, FromQuery, Get, Head, Header, HttpCode, Optional, Options, Patch, Post, Produces, Put, Redirect, RequestDto, Sse, UseGuards, UseInterceptors, Version, } from './decorators.js';
|
|
5
|
-
export * from './dispatch/dispatcher.js';
|
|
6
|
-
export type { FastPathEligibility, FastPathStats } from './dispatch/fast-path/index.js';
|
|
7
|
-
export { FAST_PATH_ELIGIBILITY_SYMBOL, FAST_PATH_STATS_SYMBOL, formatFastPathStats, getDispatcherFastPathStats, } from './dispatch/dispatcher.js';
|
|
8
|
-
export * from './errors.js';
|
|
9
|
-
export * from './exceptions.js';
|
|
10
|
-
export * from './mapping.js';
|
|
11
|
-
export { forRoutes, isMiddlewareRouteConfig, matchRoutePattern, normalizeRoutePattern, } from './middleware/middleware.js';
|
|
12
|
-
export * from './middleware/rate-limit.js';
|
|
13
|
-
export * from './context/request-context.js';
|
|
14
|
-
export * from './middleware/security-headers.js';
|
|
15
|
-
export * from './context/sse.js';
|
|
16
|
-
export * from './types.js';
|
|
1
|
+
export * from './index.portable.js';
|
|
17
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,cAAc,qBAAqB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export
|
|
5
|
-
export * from './dispatch/dispatcher.js';
|
|
6
|
-
export { FAST_PATH_ELIGIBILITY_SYMBOL, FAST_PATH_STATS_SYMBOL, formatFastPathStats, getDispatcherFastPathStats } from './dispatch/dispatcher.js';
|
|
7
|
-
export * from './errors.js';
|
|
8
|
-
export * from './exceptions.js';
|
|
9
|
-
export * from './mapping.js';
|
|
10
|
-
export { forRoutes, isMiddlewareRouteConfig, matchRoutePattern, normalizeRoutePattern } from './middleware/middleware.js';
|
|
11
|
-
export * from './middleware/rate-limit.js';
|
|
12
|
-
export * from './context/request-context.js';
|
|
13
|
-
export * from './middleware/security-headers.js';
|
|
14
|
-
export * from './context/sse.js';
|
|
15
|
-
export * from './types.js';
|
|
1
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
+
import { registerImmediateAsyncLocalStorageConstructor } from './context/request-context-node-store.js';
|
|
3
|
+
registerImmediateAsyncLocalStorageConstructor(AsyncLocalStorage);
|
|
4
|
+
export * from './index.portable.js';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export * from './adapter.js';
|
|
2
|
+
export * from './access-log-observer.js';
|
|
3
|
+
export { createByteRangeResponse, } from './byte-range-response.js';
|
|
4
|
+
export type { ByteRangeResponseOptions, ByteRangeResponseSource, } from './byte-range-response.js';
|
|
5
|
+
export { createStaticAssetsMiddleware, } from './static-assets.js';
|
|
6
|
+
export type { StaticAsset, StaticAssetAcceptedEncoding, StaticAssetContentEncoding, StaticAssetNotAcceptable, StaticAssetResolveContext, StaticAssetResolution, StaticAssetSource, StaticAssetsMiddleware, StaticAssetsMiddlewareOptions, } from './static-assets.js';
|
|
7
|
+
export * from './context/request-context.js';
|
|
8
|
+
export * from './context/sse.js';
|
|
9
|
+
export * from './connection.js';
|
|
10
|
+
export * from './cookie-helpers.js';
|
|
11
|
+
export { All, Controller, Convert, Delete, FromBody, FromCookie, FromFiles, FromHeader, FromPath, FromQuery, Get, Head, Header, HttpCode, Optional, Options, Patch, Post, Produces, Put, Query, Redirect, RequestDto, Route, Sse, UseGuards, UseInterceptors, Version, } from './decorators.js';
|
|
12
|
+
export * from './dispatch/dispatcher.js';
|
|
13
|
+
export { FAST_PATH_ELIGIBILITY_SYMBOL, FAST_PATH_STATS_SYMBOL, formatFastPathStats, getDispatcherFastPathStats, } from './dispatch/dispatcher.js';
|
|
14
|
+
export type { FastPathEligibility, FastPathStats } from './dispatch/fast-path/index.js';
|
|
15
|
+
export * from './errors.js';
|
|
16
|
+
export * from './exceptions.js';
|
|
17
|
+
export { appendVaryHeader, buildContentDisposition, getRequestHeader, getResponseHeader, hasResponseHeader, } from './header-helpers.js';
|
|
18
|
+
export * from './mapping.js';
|
|
19
|
+
export * from './middleware/correlation.js';
|
|
20
|
+
export * from './middleware/cors.js';
|
|
21
|
+
export { forRoutes, isMiddlewareRouteConfig, matchRoutePattern, normalizeRoutePattern, } from './middleware/middleware.js';
|
|
22
|
+
export * from './middleware/rate-limit.js';
|
|
23
|
+
export * from './middleware/security-headers.js';
|
|
24
|
+
export * from './types.js';
|
|
25
|
+
//# sourceMappingURL=index.portable.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.portable.d.ts","sourceRoot":"","sources":["../src/index.portable.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,0BAA0B,CAAC;AACzC,OAAO,EACL,uBAAuB,GACxB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,4BAA4B,GAC7B,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,WAAW,EACX,2BAA2B,EAC3B,0BAA0B,EAC1B,wBAAwB,EACxB,yBAAyB,EACzB,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,EACtB,6BAA6B,GAC9B,MAAM,oBAAoB,CAAC;AAC5B,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EACL,GAAG,EACH,UAAU,EACV,OAAO,EACP,MAAM,EACN,QAAQ,EACR,UAAU,EACV,SAAS,EACT,UAAU,EACV,QAAQ,EACR,SAAS,EACT,GAAG,EACH,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,KAAK,EACL,IAAI,EACJ,QAAQ,EACR,GAAG,EACH,KAAK,EACL,QAAQ,EACR,UAAU,EACV,KAAK,EACL,GAAG,EACH,SAAS,EACT,eAAe,EACf,OAAO,GACR,MAAM,iBAAiB,CAAC;AACzB,cAAc,0BAA0B,CAAC;AACzC,OAAO,EACL,4BAA4B,EAC5B,sBAAsB,EACtB,mBAAmB,EACnB,0BAA0B,GAC3B,MAAM,0BAA0B,CAAC;AAClC,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACxF,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,qBAAqB,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,OAAO,EACL,SAAS,EACT,uBAAuB,EACvB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,4BAA4B,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,kCAAkC,CAAC;AACjD,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export * from './adapter.js';
|
|
2
|
+
export * from './access-log-observer.js';
|
|
3
|
+
export { createByteRangeResponse } from './byte-range-response.js';
|
|
4
|
+
export { createStaticAssetsMiddleware } from './static-assets.js';
|
|
5
|
+
export * from './context/request-context.js';
|
|
6
|
+
export * from './context/sse.js';
|
|
7
|
+
export * from './connection.js';
|
|
8
|
+
export * from './cookie-helpers.js';
|
|
9
|
+
export { All, Controller, Convert, Delete, FromBody, FromCookie, FromFiles, FromHeader, FromPath, FromQuery, Get, Head, Header, HttpCode, Optional, Options, Patch, Post, Produces, Put, Query, Redirect, RequestDto, Route, Sse, UseGuards, UseInterceptors, Version } from './decorators.js';
|
|
10
|
+
export * from './dispatch/dispatcher.js';
|
|
11
|
+
export { FAST_PATH_ELIGIBILITY_SYMBOL, FAST_PATH_STATS_SYMBOL, formatFastPathStats, getDispatcherFastPathStats } from './dispatch/dispatcher.js';
|
|
12
|
+
export * from './errors.js';
|
|
13
|
+
export * from './exceptions.js';
|
|
14
|
+
export { appendVaryHeader, buildContentDisposition, getRequestHeader, getResponseHeader, hasResponseHeader } from './header-helpers.js';
|
|
15
|
+
export * from './mapping.js';
|
|
16
|
+
export * from './middleware/correlation.js';
|
|
17
|
+
export * from './middleware/cors.js';
|
|
18
|
+
export { forRoutes, isMiddlewareRouteConfig, matchRoutePattern, normalizeRoutePattern } from './middleware/middleware.js';
|
|
19
|
+
export * from './middleware/rate-limit.js';
|
|
20
|
+
export * from './middleware/security-headers.js';
|
|
21
|
+
export * from './types.js';
|
package/dist/internal.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { createFetchStyleHttpAdapterRealtimeCapability, type HttpApplicationAdapter, } from './adapter.js';
|
|
2
2
|
export { DefaultBinder } from './adapters/binding.js';
|
|
3
3
|
export { resolveClientIdentity } from './client-identity.js';
|
|
4
|
+
export { getCompiledRouteIdentity } from './compiled-route-identity.js';
|
|
5
|
+
export { FRAMEWORK_RESPONSE_VALUE_FINALIZER, FRAMEWORK_RESPONSE_WRITER, registerFrameworkResponseValueFinalizer, registerFrameworkResponseWriter, type FrameworkResponseValueFinalizer, type FrameworkResponseValueFinalizerContext, type FrameworkResponseWriter, type FrameworkResponseWriterContext, } from './dispatch/response-integration.js';
|
|
6
|
+
export { attachFrameworkRequestNativeRouteHandoff, bindRawRequestNativeRouteHandoff, consumeRawRequestNativeRouteHandoff, isRoutePathNormalizationSensitive, type NativeRouteHandoff, readFrameworkRequestNativeRouteHandoff, } from './dispatch/native-route-handoff.js';
|
|
4
7
|
export type { Dispatcher } from './types.js';
|
|
5
|
-
export { attachFrameworkRequestNativeRouteHandoff, bindRawRequestNativeRouteHandoff, consumeRawRequestNativeRouteHandoff, isRoutePathNormalizationSensitive, readFrameworkRequestNativeRouteHandoff, type NativeRouteHandoff, } from './dispatch/native-route-handoff.js';
|
|
6
8
|
//# sourceMappingURL=internal.d.ts.map
|
package/dist/internal.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,6CAA6C,EAC7C,KAAK,sBAAsB,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,
|
|
1
|
+
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,6CAA6C,EAC7C,KAAK,sBAAsB,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EACL,kCAAkC,EAClC,yBAAyB,EACzB,uCAAuC,EACvC,+BAA+B,EAC/B,KAAK,+BAA+B,EACpC,KAAK,sCAAsC,EAC3C,KAAK,uBAAuB,EAC5B,KAAK,8BAA8B,GACpC,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,wCAAwC,EACxC,gCAAgC,EAChC,mCAAmC,EACnC,iCAAiC,EACjC,KAAK,kBAAkB,EACvB,sCAAsC,GACvC,MAAM,oCAAoC,CAAC;AAC5C,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/internal.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { createFetchStyleHttpAdapterRealtimeCapability } from './adapter.js';
|
|
2
2
|
export { DefaultBinder } from './adapters/binding.js';
|
|
3
3
|
export { resolveClientIdentity } from './client-identity.js';
|
|
4
|
+
export { getCompiledRouteIdentity } from './compiled-route-identity.js';
|
|
5
|
+
export { FRAMEWORK_RESPONSE_VALUE_FINALIZER, FRAMEWORK_RESPONSE_WRITER, registerFrameworkResponseValueFinalizer, registerFrameworkResponseWriter } from './dispatch/response-integration.js';
|
|
4
6
|
export { attachFrameworkRequestNativeRouteHandoff, bindRawRequestNativeRouteHandoff, consumeRawRequestNativeRouteHandoff, isRoutePathNormalizationSensitive, readFrameworkRequestNativeRouteHandoff } from './dispatch/native-route-handoff.js';
|
package/dist/mapping.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../src/mapping.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../src/mapping.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAIV,cAAc,EAId,aAAa,EAOb,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAQpB,UAAU,2BAA2B;IACnC,UAAU,CAAC,EAAE,iBAAiB,CAAC;CAChC;AAycD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,OAAO,CAAC,EAAE,2BAA2B,GAAG,cAAc,CA8EpH"}
|
package/dist/mapping.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { getControllerMetadata, getRouteMetadata } from '@fluojs/core/internal';
|
|
2
|
+
import { attachCompiledRouteIdentity } from './compiled-route-identity.js';
|
|
2
3
|
import { getRouteProducesMetadata } from './decorators.js';
|
|
3
4
|
import { RouteConflictError } from './errors.js';
|
|
5
|
+
import { isMiddlewareRouteConfig } from './middleware/middleware.js';
|
|
4
6
|
import { extractRoutePathParams, normalizeRoutePath, parseRoutePath } from './route-path.js';
|
|
5
7
|
import { VersioningType } from './types.js';
|
|
6
8
|
function joinPaths(basePath, routePath) {
|
|
@@ -19,16 +21,27 @@ function applyVersionPrefix(path, version) {
|
|
|
19
21
|
function normalizeVersionValue(version) {
|
|
20
22
|
return version.trim().replace(/^v/i, '');
|
|
21
23
|
}
|
|
22
|
-
function
|
|
23
|
-
const
|
|
24
|
+
function normalizeHeaderName(headerName) {
|
|
25
|
+
const normalized = headerName.trim().toLowerCase();
|
|
26
|
+
return normalized.length > 0 ? normalized : undefined;
|
|
27
|
+
}
|
|
28
|
+
function getMatchingRequestHeaderValues(request, headerName) {
|
|
29
|
+
const normalizedHeaderName = normalizeHeaderName(headerName);
|
|
24
30
|
if (!normalizedHeaderName) {
|
|
25
|
-
return
|
|
31
|
+
return [];
|
|
26
32
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
33
|
+
const matches = [];
|
|
34
|
+
for (const [name, value] of Object.entries(request.headers)) {
|
|
35
|
+
if (name.toLowerCase() === normalizedHeaderName) {
|
|
36
|
+
matches.push(value);
|
|
30
37
|
}
|
|
31
|
-
|
|
38
|
+
}
|
|
39
|
+
return matches;
|
|
40
|
+
}
|
|
41
|
+
function readHeaderValue(request, headerName) {
|
|
42
|
+
const matches = getMatchingRequestHeaderValues(request, headerName);
|
|
43
|
+
for (const match of matches) {
|
|
44
|
+
const values = Array.isArray(match) ? match : [match];
|
|
32
45
|
for (const value of values) {
|
|
33
46
|
const normalized = value?.trim();
|
|
34
47
|
if (normalized) {
|
|
@@ -38,11 +51,25 @@ function readHeaderValue(request, headerName) {
|
|
|
38
51
|
}
|
|
39
52
|
return undefined;
|
|
40
53
|
}
|
|
54
|
+
function readCombinedHeaderValue(request, headerName) {
|
|
55
|
+
const matches = getMatchingRequestHeaderValues(request, headerName);
|
|
56
|
+
const values = [];
|
|
57
|
+
for (const match of matches) {
|
|
58
|
+
const entries = Array.isArray(match) ? match : [match];
|
|
59
|
+
for (const entry of entries) {
|
|
60
|
+
const normalized = entry?.trim();
|
|
61
|
+
if (normalized) {
|
|
62
|
+
values.push(normalized);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return values.length > 0 ? values.join(',') : undefined;
|
|
67
|
+
}
|
|
41
68
|
function escapeRegExp(value) {
|
|
42
69
|
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
43
70
|
}
|
|
44
71
|
function extractVersionFromMediaType(request, key) {
|
|
45
|
-
const accept =
|
|
72
|
+
const accept = readCombinedHeaderValue(request, 'accept');
|
|
46
73
|
if (!accept) {
|
|
47
74
|
return undefined;
|
|
48
75
|
}
|
|
@@ -209,12 +236,12 @@ function matchParameterizedRoute(candidate, incomingSegments) {
|
|
|
209
236
|
}
|
|
210
237
|
return params;
|
|
211
238
|
}
|
|
212
|
-
function createHandlerDescriptors(source, versioning) {
|
|
239
|
+
function createHandlerDescriptors(source, versioning, sourceIndex) {
|
|
213
240
|
const controllerMetadata = getControllerMetadata(source.controllerToken) ?? {
|
|
214
241
|
basePath: ''
|
|
215
242
|
};
|
|
216
243
|
const descriptors = [];
|
|
217
|
-
for (const propertyKey of getControllerMethodNames(source.controllerToken)) {
|
|
244
|
+
for (const [methodIndex, propertyKey] of getControllerMethodNames(source.controllerToken).entries()) {
|
|
218
245
|
const routeMetadata = getRouteMetadata(source.controllerToken.prototype, propertyKey);
|
|
219
246
|
if (!routeMetadata) {
|
|
220
247
|
continue;
|
|
@@ -223,7 +250,7 @@ function createHandlerDescriptors(source, versioning) {
|
|
|
223
250
|
const routePath = joinPaths(controllerMetadata.basePath, routeMetadata.path);
|
|
224
251
|
const effectivePath = versioning.type === VersioningType.URI ? applyVersionPrefix(routePath, effectiveVersion) : routePath;
|
|
225
252
|
const produces = getRouteProducesMetadata(source.controllerToken, propertyKey);
|
|
226
|
-
descriptors.push({
|
|
253
|
+
descriptors.push(attachCompiledRouteIdentity({
|
|
227
254
|
controllerToken: source.controllerToken,
|
|
228
255
|
metadata: {
|
|
229
256
|
controllerPath: controllerMetadata.basePath,
|
|
@@ -244,12 +271,12 @@ function createHandlerDescriptors(source, versioning) {
|
|
|
244
271
|
path: effectivePath,
|
|
245
272
|
version: effectiveVersion
|
|
246
273
|
}
|
|
247
|
-
});
|
|
274
|
+
}, `v1:${sourceIndex}:${methodIndex}`));
|
|
248
275
|
}
|
|
249
276
|
return descriptors;
|
|
250
277
|
}
|
|
251
278
|
function buildDescriptorList(sources, versioning) {
|
|
252
|
-
const descriptors = sources.flatMap(source => createHandlerDescriptors(source, versioning));
|
|
279
|
+
const descriptors = sources.flatMap((source, sourceIndex) => createHandlerDescriptors(source, versioning, sourceIndex));
|
|
253
280
|
const seen = new Set();
|
|
254
281
|
for (const descriptor of descriptors) {
|
|
255
282
|
const routeVersion = descriptor.route.version === undefined ? '<none>' : normalizeVersionValue(descriptor.route.version);
|
|
@@ -261,6 +288,59 @@ function buildDescriptorList(sources, versioning) {
|
|
|
261
288
|
}
|
|
262
289
|
return descriptors;
|
|
263
290
|
}
|
|
291
|
+
function freezeDescriptorSnapshot(descriptors) {
|
|
292
|
+
const snapshot = descriptors.map(descriptor => {
|
|
293
|
+
const {
|
|
294
|
+
metadata,
|
|
295
|
+
route
|
|
296
|
+
} = descriptor;
|
|
297
|
+
const frozenMetadata = Object.freeze({
|
|
298
|
+
...metadata,
|
|
299
|
+
moduleMiddleware: freezeModuleMiddlewareSnapshot(metadata.moduleMiddleware),
|
|
300
|
+
pathParams: Object.freeze([...metadata.pathParams])
|
|
301
|
+
});
|
|
302
|
+
const frozenRoute = Object.freeze({
|
|
303
|
+
...route,
|
|
304
|
+
...(route.guards ? {
|
|
305
|
+
guards: Object.freeze([...route.guards])
|
|
306
|
+
} : {}),
|
|
307
|
+
...(route.headers ? {
|
|
308
|
+
headers: Object.freeze(route.headers.map(header => Object.freeze({
|
|
309
|
+
...header
|
|
310
|
+
})))
|
|
311
|
+
} : {}),
|
|
312
|
+
...(route.interceptors ? {
|
|
313
|
+
interceptors: Object.freeze([...route.interceptors])
|
|
314
|
+
} : {}),
|
|
315
|
+
...(route.produces ? {
|
|
316
|
+
produces: Object.freeze([...route.produces])
|
|
317
|
+
} : {}),
|
|
318
|
+
...(route.redirect ? {
|
|
319
|
+
redirect: Object.freeze({
|
|
320
|
+
...route.redirect
|
|
321
|
+
})
|
|
322
|
+
} : {})
|
|
323
|
+
});
|
|
324
|
+
return Object.freeze({
|
|
325
|
+
...descriptor,
|
|
326
|
+
metadata: frozenMetadata,
|
|
327
|
+
route: frozenRoute
|
|
328
|
+
});
|
|
329
|
+
});
|
|
330
|
+
return Object.freeze(snapshot);
|
|
331
|
+
}
|
|
332
|
+
function freezeModuleMiddlewareSnapshot(definitions) {
|
|
333
|
+
const snapshot = definitions.map(definition => {
|
|
334
|
+
if (!isMiddlewareRouteConfig(definition)) {
|
|
335
|
+
return definition;
|
|
336
|
+
}
|
|
337
|
+
return Object.freeze({
|
|
338
|
+
middleware: definition.middleware,
|
|
339
|
+
routes: Object.freeze([...definition.routes])
|
|
340
|
+
});
|
|
341
|
+
});
|
|
342
|
+
return Object.freeze(snapshot);
|
|
343
|
+
}
|
|
264
344
|
|
|
265
345
|
/**
|
|
266
346
|
* Create handler mapping.
|
|
@@ -271,9 +351,9 @@ function buildDescriptorList(sources, versioning) {
|
|
|
271
351
|
*/
|
|
272
352
|
export function createHandlerMapping(sources, options) {
|
|
273
353
|
const versioning = resolveVersioning(options);
|
|
274
|
-
const descriptors = buildDescriptorList(sources, versioning);
|
|
354
|
+
const descriptors = freezeDescriptorSnapshot(buildDescriptorList(sources, versioning));
|
|
275
355
|
const descriptorIndex = buildDescriptorIndex(descriptors);
|
|
276
|
-
|
|
356
|
+
const mapping = {
|
|
277
357
|
descriptors,
|
|
278
358
|
match(request) {
|
|
279
359
|
const method = request.method.toUpperCase();
|
|
@@ -323,4 +403,9 @@ export function createHandlerMapping(sources, options) {
|
|
|
323
403
|
return undefined;
|
|
324
404
|
}
|
|
325
405
|
};
|
|
406
|
+
Object.defineProperty(mapping, 'descriptors', {
|
|
407
|
+
configurable: false,
|
|
408
|
+
writable: false
|
|
409
|
+
});
|
|
410
|
+
return mapping;
|
|
326
411
|
}
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import type { Middleware } from '../types.js';
|
|
1
|
+
import type { Middleware, MiddlewareLike, RequestContext } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Initializes correlation-aware request contexts before lifecycle observers run.
|
|
4
|
+
*
|
|
5
|
+
* @internal
|
|
6
|
+
* @param middleware Global middleware definitions registered with the dispatcher.
|
|
7
|
+
* @param context Request context to initialize.
|
|
8
|
+
*/
|
|
9
|
+
export declare function initializeCorrelationMiddlewareRequestContext(middleware: readonly MiddlewareLike[], context: RequestContext): void;
|
|
2
10
|
/**
|
|
3
11
|
* Create correlation middleware.
|
|
4
12
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"correlation.d.ts","sourceRoot":"","sources":["../../src/middleware/correlation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"correlation.d.ts","sourceRoot":"","sources":["../../src/middleware/correlation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAoB,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAuBhG;;;;;;GAMG;AACH,wBAAgB,6CAA6C,CAC3D,UAAU,EAAE,SAAS,cAAc,EAAE,EACrC,OAAO,EAAE,cAAc,GACtB,IAAI,CAUN;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,IAAI,UAAU,CAWxD"}
|
|
@@ -1,16 +1,28 @@
|
|
|
1
|
+
import { resolveRequestId } from '../context/request-id.js';
|
|
1
2
|
const REQUEST_ID_HEADER = 'x-request-id';
|
|
2
|
-
const
|
|
3
|
-
function
|
|
4
|
-
const requestId =
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
const CORRELATION_REQUEST_CONTEXT_INITIALIZER = Symbol('fluo.http.correlationRequestContextInitializer');
|
|
4
|
+
function initializeCorrelationRequestContext(context, request = context.request) {
|
|
5
|
+
const requestId = context.requestId ?? resolveRequestId(request);
|
|
6
|
+
if (requestId === undefined) {
|
|
7
|
+
throw new Error('Correlation request ID generation unexpectedly returned undefined.');
|
|
8
|
+
}
|
|
9
|
+
context.requestId = requestId;
|
|
10
|
+
return requestId;
|
|
7
11
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Initializes correlation-aware request contexts before lifecycle observers run.
|
|
15
|
+
*
|
|
16
|
+
* @internal
|
|
17
|
+
* @param middleware Global middleware definitions registered with the dispatcher.
|
|
18
|
+
* @param context Request context to initialize.
|
|
19
|
+
*/
|
|
20
|
+
export function initializeCorrelationMiddlewareRequestContext(middleware, context) {
|
|
21
|
+
for (const definition of middleware) {
|
|
22
|
+
if (typeof definition === 'object' && definition !== null && CORRELATION_REQUEST_CONTEXT_INITIALIZER in definition) {
|
|
23
|
+
definition[CORRELATION_REQUEST_CONTEXT_INITIALIZER](context);
|
|
24
|
+
}
|
|
12
25
|
}
|
|
13
|
-
return `req_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`;
|
|
14
26
|
}
|
|
15
27
|
|
|
16
28
|
/**
|
|
@@ -20,11 +32,10 @@ function createRequestId() {
|
|
|
20
32
|
*/
|
|
21
33
|
export function createCorrelationMiddleware() {
|
|
22
34
|
return {
|
|
35
|
+
[CORRELATION_REQUEST_CONTEXT_INITIALIZER]: initializeCorrelationRequestContext,
|
|
23
36
|
async handle(context, next) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
context.response.setHeader(REQUEST_ID_HEADER, context.requestContext.requestId);
|
|
37
|
+
const requestId = initializeCorrelationRequestContext(context.requestContext, context.request);
|
|
38
|
+
context.response.setHeader(REQUEST_ID_HEADER, requestId);
|
|
28
39
|
await next();
|
|
29
40
|
}
|
|
30
41
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,KAAK,MAAM,GAAG,SAAS,CAAC,CAAC;IACvF,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA4BD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,WAAgB,GAAG,UAAU,CA0D1E"}
|
package/dist/middleware/cors.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { appendVaryHeader, getRequestHeader } from '../header-helpers.js';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Describes the cors options contract.
|
|
3
5
|
*/
|
|
@@ -35,7 +37,7 @@ export function createCorsMiddleware(options = {}) {
|
|
|
35
37
|
const allowMethods = options.allowMethods ?? ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'];
|
|
36
38
|
return {
|
|
37
39
|
async handle(context, next) {
|
|
38
|
-
const requestOriginHeader = context.request
|
|
40
|
+
const requestOriginHeader = getRequestHeader(context.request, 'origin');
|
|
39
41
|
const requestOrigin = Array.isArray(requestOriginHeader) ? requestOriginHeader[0] : requestOriginHeader;
|
|
40
42
|
const origin = resolveOrigin(options, requestOrigin);
|
|
41
43
|
if (origin) {
|
|
@@ -50,14 +52,11 @@ export function createCorsMiddleware(options = {}) {
|
|
|
50
52
|
setHeaderIfValue(context.response, 'Access-Control-Allow-Credentials', options.allowCredentials ? 'true' : undefined);
|
|
51
53
|
setHeaderIfValue(context.response, 'Access-Control-Max-Age', options.maxAge !== undefined ? String(options.maxAge) : undefined);
|
|
52
54
|
if (origin && origin !== '*') {
|
|
53
|
-
|
|
54
|
-
const varyValues = existingVary ? Array.isArray(existingVary) ? existingVary : String(existingVary).split(',').map(v => v.trim()) : [];
|
|
55
|
-
if (!varyValues.some(v => v.toLowerCase() === 'origin')) {
|
|
56
|
-
varyValues.push('Origin');
|
|
57
|
-
}
|
|
58
|
-
context.response.setHeader('Vary', varyValues.join(', '));
|
|
55
|
+
appendVaryHeader(context.response, 'Origin');
|
|
59
56
|
}
|
|
60
|
-
|
|
57
|
+
const requestedPreflightMethod = getRequestHeader(context.request, 'access-control-request-method');
|
|
58
|
+
const hasPreflightMethod = Array.isArray(requestedPreflightMethod) ? requestedPreflightMethod.length > 0 : requestedPreflightMethod !== undefined;
|
|
59
|
+
if (context.request.method === 'OPTIONS' && hasPreflightMethod) {
|
|
61
60
|
context.response.setStatus(204);
|
|
62
61
|
await context.response.send(undefined);
|
|
63
62
|
return;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { Constructor } from '@fluojs/core';
|
|
2
|
-
import type { Middleware, MiddlewareContext, MiddlewareLike, MiddlewareRouteConfig, Next } from '../types.js';
|
|
2
|
+
import type { Middleware, MiddlewareContext, MiddlewareLike, MiddlewareRouteConfig, MiddlewareRouteSnapshot, MiddlewareSnapshotLike, Next } from '../types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Is middleware route config.
|
|
5
5
|
*
|
|
6
6
|
* @param value The value.
|
|
7
7
|
* @returns The is middleware route config result.
|
|
8
8
|
*/
|
|
9
|
-
export declare function isMiddlewareRouteConfig(value: MiddlewareLike): value is MiddlewareRouteConfig;
|
|
9
|
+
export declare function isMiddlewareRouteConfig(value: MiddlewareLike | MiddlewareSnapshotLike): value is MiddlewareRouteConfig | MiddlewareRouteSnapshot;
|
|
10
10
|
/**
|
|
11
11
|
* Normalize route pattern.
|
|
12
12
|
*
|
|
@@ -38,5 +38,5 @@ export declare function forRoutes<T extends Constructor<Middleware>>(middlewareC
|
|
|
38
38
|
* @param terminal The terminal.
|
|
39
39
|
* @returns The run middleware chain result.
|
|
40
40
|
*/
|
|
41
|
-
export declare function runMiddlewareChain(definitions: MiddlewareLike[], context: MiddlewareContext, terminal: Next): Promise<void>;
|
|
41
|
+
export declare function runMiddlewareChain(definitions: readonly (MiddlewareLike | MiddlewareSnapshotLike)[], context: MiddlewareContext, terminal: Next): Promise<void>;
|
|
42
42
|
//# sourceMappingURL=middleware.d.ts.map
|