@chidchanun/bcp 0.1.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/CHANGELOG.md +49 -0
- package/LICENSE +21 -0
- package/README.md +241 -0
- package/docs/caching.md +76 -0
- package/docs/configuration.md +97 -0
- package/docs/deployment.md +74 -0
- package/docs/getting-started.md +82 -0
- package/docs/middleware.md +58 -0
- package/docs/releasing.md +299 -0
- package/docs/routing.md +103 -0
- package/docs/security.md +57 -0
- package/package.json +68 -0
- package/packages/bundler/src/client-islands.ts +1457 -0
- package/packages/bundler/src/incremental-context.ts +206 -0
- package/packages/bundler/src/index.ts +1991 -0
- package/packages/bundler/src/module-graph.ts +317 -0
- package/packages/bundler/src/partial-hydration.ts +414 -0
- package/packages/bundler/src/production.ts +974 -0
- package/packages/bundler/src/server-production-middleware.ts +447 -0
- package/packages/bundler/src/server-production.ts +1193 -0
- package/packages/bundler/src/special-files.ts +131 -0
- package/packages/cache/src/index.ts +761 -0
- package/packages/cli/bin/bcp.mjs +93 -0
- package/packages/cli/src/args.ts +305 -0
- package/packages/cli/src/bootstrap.ts +514 -0
- package/packages/cli/src/index.ts +504 -0
- package/packages/cli/src/version.ts +45 -0
- package/packages/client/src/cache.ts +11 -0
- package/packages/client/src/config.ts +18 -0
- package/packages/client/src/error-boundary.tsx +149 -0
- package/packages/client/src/hydration.ts +3 -0
- package/packages/client/src/index.tsx +57 -0
- package/packages/client/src/islands.tsx +315 -0
- package/packages/client/src/metadata.ts +281 -0
- package/packages/client/src/navigation-loading.ts +52 -0
- package/packages/client/src/navigation-state.ts +80 -0
- package/packages/client/src/not-found.ts +34 -0
- package/packages/client/src/persistent-layout-runtime.ts +273 -0
- package/packages/client/src/router-v2.tsx +969 -0
- package/packages/client/src/router.tsx +1 -0
- package/packages/config/src/index.ts +1038 -0
- package/packages/env/src/index.ts +593 -0
- package/packages/router/src/advanced-router.ts +1032 -0
- package/packages/router/src/index.ts +1 -0
- package/packages/server/src/compression.ts +249 -0
- package/packages/server/src/dev-document-metadata.ts +154 -0
- package/packages/server/src/dev-hmr.ts +225 -0
- package/packages/server/src/index.ts +2265 -0
- package/packages/server/src/metadata.ts +478 -0
- package/packages/server/src/middleware-dev-server.ts +260 -0
- package/packages/server/src/middleware-loader.ts +140 -0
- package/packages/server/src/middleware-proxy.ts +516 -0
- package/packages/server/src/middleware.ts +704 -0
- package/packages/server/src/navigation-payload.ts +471 -0
- package/packages/server/src/production-server.ts +1746 -0
- package/packages/server/src/response-cache-proxy.ts +828 -0
- package/packages/server/src/security-proxy.ts +406 -0
- package/packages/server/src/security.ts +451 -0
- package/packages/server/src/standalone-production-runtime-v2.ts +2047 -0
- package/packages/server/src/standalone-production-runtime-v3.ts +250 -0
- package/packages/server/src/standalone-production-runtime-v4.ts +289 -0
- package/packages/server/src/standalone-production-runtime-v5.ts +289 -0
- package/packages/server/src/standalone-production-runtime.ts +1951 -0
- package/packages/server/src/standalone-production-server.ts +6 -0
- package/packages/server/src/static-assets.ts +262 -0
- package/packages/server/src/static-dev-server.ts +854 -0
|
@@ -0,0 +1,704 @@
|
|
|
1
|
+
import type * as http from "node:http";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
assertSafeMiddlewareTarget,
|
|
5
|
+
} from "./security.js";
|
|
6
|
+
|
|
7
|
+
export type MiddlewareMatcher =
|
|
8
|
+
| string
|
|
9
|
+
| RegExp;
|
|
10
|
+
|
|
11
|
+
export interface MiddlewareConfig {
|
|
12
|
+
matcher?:
|
|
13
|
+
| MiddlewareMatcher
|
|
14
|
+
| MiddlewareMatcher[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface MiddlewareCookieStore {
|
|
18
|
+
get(name: string): string | null;
|
|
19
|
+
has(name: string): boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface MiddlewareRequest {
|
|
23
|
+
readonly url: string;
|
|
24
|
+
readonly method: string;
|
|
25
|
+
readonly headers: Headers;
|
|
26
|
+
readonly nextUrl: URL;
|
|
27
|
+
readonly cookies: MiddlewareCookieStore;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface MiddlewareHeaderOptions {
|
|
31
|
+
request?: {
|
|
32
|
+
headers?: HeadersInit;
|
|
33
|
+
};
|
|
34
|
+
response?: {
|
|
35
|
+
headers?: HeadersInit;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface MiddlewareRedirectOptions {
|
|
40
|
+
status?: 301 | 302 | 303 | 307 | 308;
|
|
41
|
+
headers?: HeadersInit;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface MiddlewareNextResult {
|
|
45
|
+
readonly type: "next";
|
|
46
|
+
readonly requestHeaders: Headers;
|
|
47
|
+
readonly responseHeaders: Headers;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface MiddlewareRewriteResult {
|
|
51
|
+
readonly type: "rewrite";
|
|
52
|
+
readonly url: string;
|
|
53
|
+
readonly requestHeaders: Headers;
|
|
54
|
+
readonly responseHeaders: Headers;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface MiddlewareRedirectResult {
|
|
58
|
+
readonly type: "redirect";
|
|
59
|
+
readonly url: string;
|
|
60
|
+
readonly status: 301 | 302 | 303 | 307 | 308;
|
|
61
|
+
readonly headers: Headers;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export type MiddlewareResult =
|
|
65
|
+
| MiddlewareNextResult
|
|
66
|
+
| MiddlewareRewriteResult
|
|
67
|
+
| MiddlewareRedirectResult;
|
|
68
|
+
|
|
69
|
+
export type MiddlewareHandler = (
|
|
70
|
+
request: MiddlewareRequest
|
|
71
|
+
) =>
|
|
72
|
+
| MiddlewareResult
|
|
73
|
+
| Response
|
|
74
|
+
| void
|
|
75
|
+
| Promise<
|
|
76
|
+
MiddlewareResult |
|
|
77
|
+
Response |
|
|
78
|
+
void
|
|
79
|
+
>;
|
|
80
|
+
|
|
81
|
+
export interface MiddlewareModule {
|
|
82
|
+
middleware?: MiddlewareHandler;
|
|
83
|
+
default?: MiddlewareHandler;
|
|
84
|
+
config?: MiddlewareConfig;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface MiddlewareExecutionInput {
|
|
88
|
+
url: string | URL;
|
|
89
|
+
method?: string;
|
|
90
|
+
headers?: HeadersInit;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type MiddlewareExecutionResult =
|
|
94
|
+
| {
|
|
95
|
+
type: "next";
|
|
96
|
+
url: URL;
|
|
97
|
+
requestHeaders: Headers;
|
|
98
|
+
responseHeaders: Headers;
|
|
99
|
+
}
|
|
100
|
+
| {
|
|
101
|
+
type: "rewrite";
|
|
102
|
+
url: URL;
|
|
103
|
+
requestHeaders: Headers;
|
|
104
|
+
responseHeaders: Headers;
|
|
105
|
+
}
|
|
106
|
+
| {
|
|
107
|
+
type: "redirect";
|
|
108
|
+
url: URL;
|
|
109
|
+
status: 301 | 302 | 303 | 307 | 308;
|
|
110
|
+
headers: Headers;
|
|
111
|
+
}
|
|
112
|
+
| {
|
|
113
|
+
type: "response";
|
|
114
|
+
response: Response;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export function next(
|
|
118
|
+
options: MiddlewareHeaderOptions = {}
|
|
119
|
+
): MiddlewareNextResult {
|
|
120
|
+
return {
|
|
121
|
+
type: "next",
|
|
122
|
+
requestHeaders:
|
|
123
|
+
new Headers(
|
|
124
|
+
options.request?.headers
|
|
125
|
+
),
|
|
126
|
+
responseHeaders:
|
|
127
|
+
new Headers(
|
|
128
|
+
options.response?.headers
|
|
129
|
+
),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export function rewrite(
|
|
134
|
+
url: string | URL,
|
|
135
|
+
options: MiddlewareHeaderOptions = {}
|
|
136
|
+
): MiddlewareRewriteResult {
|
|
137
|
+
return {
|
|
138
|
+
type: "rewrite",
|
|
139
|
+
url:
|
|
140
|
+
url.toString(),
|
|
141
|
+
requestHeaders:
|
|
142
|
+
new Headers(
|
|
143
|
+
options.request?.headers
|
|
144
|
+
),
|
|
145
|
+
responseHeaders:
|
|
146
|
+
new Headers(
|
|
147
|
+
options.response?.headers
|
|
148
|
+
),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function redirect(
|
|
153
|
+
url: string | URL,
|
|
154
|
+
options: MiddlewareRedirectOptions = {}
|
|
155
|
+
): MiddlewareRedirectResult {
|
|
156
|
+
return {
|
|
157
|
+
type: "redirect",
|
|
158
|
+
url:
|
|
159
|
+
url.toString(),
|
|
160
|
+
status:
|
|
161
|
+
options.status ?? 307,
|
|
162
|
+
headers:
|
|
163
|
+
new Headers(
|
|
164
|
+
options.headers
|
|
165
|
+
),
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export async function executeMiddleware(
|
|
170
|
+
module: MiddlewareModule | null | undefined,
|
|
171
|
+
input: MiddlewareExecutionInput
|
|
172
|
+
): Promise<MiddlewareExecutionResult> {
|
|
173
|
+
const originalUrl =
|
|
174
|
+
input.url instanceof URL
|
|
175
|
+
? new URL(
|
|
176
|
+
input.url.href
|
|
177
|
+
)
|
|
178
|
+
: new URL(
|
|
179
|
+
input.url
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
const baseHeaders =
|
|
183
|
+
new Headers(
|
|
184
|
+
input.headers
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
const passthrough =
|
|
188
|
+
(): MiddlewareExecutionResult => ({
|
|
189
|
+
type: "next",
|
|
190
|
+
url:
|
|
191
|
+
originalUrl,
|
|
192
|
+
requestHeaders:
|
|
193
|
+
baseHeaders,
|
|
194
|
+
responseHeaders:
|
|
195
|
+
new Headers(),
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
if (
|
|
199
|
+
!module ||
|
|
200
|
+
isFrameworkInternalPath(
|
|
201
|
+
originalUrl.pathname
|
|
202
|
+
)
|
|
203
|
+
) {
|
|
204
|
+
return passthrough();
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const handler =
|
|
208
|
+
module.middleware ??
|
|
209
|
+
module.default;
|
|
210
|
+
|
|
211
|
+
if (!handler) {
|
|
212
|
+
return passthrough();
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (
|
|
216
|
+
!matchesMiddleware(
|
|
217
|
+
originalUrl.pathname,
|
|
218
|
+
module.config?.matcher
|
|
219
|
+
)
|
|
220
|
+
) {
|
|
221
|
+
return passthrough();
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const request:
|
|
225
|
+
MiddlewareRequest = {
|
|
226
|
+
url:
|
|
227
|
+
originalUrl.href,
|
|
228
|
+
method:
|
|
229
|
+
input.method ??
|
|
230
|
+
"GET",
|
|
231
|
+
headers:
|
|
232
|
+
baseHeaders,
|
|
233
|
+
nextUrl:
|
|
234
|
+
originalUrl,
|
|
235
|
+
cookies:
|
|
236
|
+
createCookieStore(
|
|
237
|
+
baseHeaders.get(
|
|
238
|
+
"cookie"
|
|
239
|
+
)
|
|
240
|
+
),
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
const result =
|
|
244
|
+
await handler(
|
|
245
|
+
request
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
if (
|
|
249
|
+
result === undefined
|
|
250
|
+
) {
|
|
251
|
+
return passthrough();
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (
|
|
255
|
+
result instanceof Response
|
|
256
|
+
) {
|
|
257
|
+
return {
|
|
258
|
+
type: "response",
|
|
259
|
+
response:
|
|
260
|
+
result,
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (
|
|
265
|
+
result.type === "next"
|
|
266
|
+
) {
|
|
267
|
+
return {
|
|
268
|
+
type: "next",
|
|
269
|
+
url:
|
|
270
|
+
originalUrl,
|
|
271
|
+
requestHeaders:
|
|
272
|
+
mergeHeaders(
|
|
273
|
+
baseHeaders,
|
|
274
|
+
result.requestHeaders
|
|
275
|
+
),
|
|
276
|
+
responseHeaders:
|
|
277
|
+
result.responseHeaders,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (
|
|
282
|
+
result.type === "rewrite"
|
|
283
|
+
) {
|
|
284
|
+
const target =
|
|
285
|
+
new URL(
|
|
286
|
+
result.url,
|
|
287
|
+
originalUrl
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
assertSafeMiddlewareTarget(
|
|
291
|
+
target,
|
|
292
|
+
originalUrl,
|
|
293
|
+
"rewrite"
|
|
294
|
+
);
|
|
295
|
+
|
|
296
|
+
return {
|
|
297
|
+
type: "rewrite",
|
|
298
|
+
url:
|
|
299
|
+
target,
|
|
300
|
+
requestHeaders:
|
|
301
|
+
mergeHeaders(
|
|
302
|
+
baseHeaders,
|
|
303
|
+
result.requestHeaders
|
|
304
|
+
),
|
|
305
|
+
responseHeaders:
|
|
306
|
+
result.responseHeaders,
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
if (
|
|
311
|
+
result.type === "redirect"
|
|
312
|
+
) {
|
|
313
|
+
const target =
|
|
314
|
+
new URL(
|
|
315
|
+
result.url,
|
|
316
|
+
originalUrl
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
assertSafeMiddlewareTarget(
|
|
320
|
+
target,
|
|
321
|
+
originalUrl,
|
|
322
|
+
"redirect"
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
return {
|
|
326
|
+
type: "redirect",
|
|
327
|
+
url:
|
|
328
|
+
target,
|
|
329
|
+
status:
|
|
330
|
+
result.status,
|
|
331
|
+
headers:
|
|
332
|
+
result.headers,
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
throw new Error(
|
|
337
|
+
"BCP Framework: middleware returned an unsupported result."
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export function matchesMiddleware(
|
|
342
|
+
pathname: string,
|
|
343
|
+
matcher:
|
|
344
|
+
| MiddlewareConfig["matcher"]
|
|
345
|
+
| undefined
|
|
346
|
+
): boolean {
|
|
347
|
+
if (
|
|
348
|
+
matcher === undefined
|
|
349
|
+
) {
|
|
350
|
+
return true;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const matchers =
|
|
354
|
+
Array.isArray(
|
|
355
|
+
matcher
|
|
356
|
+
)
|
|
357
|
+
? matcher
|
|
358
|
+
: [
|
|
359
|
+
matcher,
|
|
360
|
+
];
|
|
361
|
+
|
|
362
|
+
if (
|
|
363
|
+
matchers.length === 0
|
|
364
|
+
) {
|
|
365
|
+
return false;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
return matchers.some(
|
|
369
|
+
(value) => {
|
|
370
|
+
if (
|
|
371
|
+
value instanceof RegExp
|
|
372
|
+
) {
|
|
373
|
+
value.lastIndex = 0;
|
|
374
|
+
return value.test(
|
|
375
|
+
pathname
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
return matchPathPattern(
|
|
380
|
+
pathname,
|
|
381
|
+
value
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
export function applyMiddlewareRequestHeaders(
|
|
388
|
+
req: http.IncomingMessage,
|
|
389
|
+
headers: Headers
|
|
390
|
+
): void {
|
|
391
|
+
const nextHeaders:
|
|
392
|
+
http.IncomingHttpHeaders = {};
|
|
393
|
+
|
|
394
|
+
headers.forEach(
|
|
395
|
+
(value, key) => {
|
|
396
|
+
nextHeaders[
|
|
397
|
+
key.toLowerCase()
|
|
398
|
+
] =
|
|
399
|
+
value;
|
|
400
|
+
}
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
req.headers =
|
|
404
|
+
nextHeaders;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
export function applyMiddlewareResponseHeaders(
|
|
408
|
+
res: http.ServerResponse,
|
|
409
|
+
headers: Headers
|
|
410
|
+
): void {
|
|
411
|
+
headers.forEach(
|
|
412
|
+
(value, key) => {
|
|
413
|
+
res.setHeader(
|
|
414
|
+
key,
|
|
415
|
+
value
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
export function sendMiddlewareRedirect(
|
|
422
|
+
req: http.IncomingMessage,
|
|
423
|
+
res: http.ServerResponse,
|
|
424
|
+
result: Extract<
|
|
425
|
+
MiddlewareExecutionResult,
|
|
426
|
+
{
|
|
427
|
+
type: "redirect";
|
|
428
|
+
}
|
|
429
|
+
>
|
|
430
|
+
): void {
|
|
431
|
+
applyMiddlewareResponseHeaders(
|
|
432
|
+
res,
|
|
433
|
+
result.headers
|
|
434
|
+
);
|
|
435
|
+
|
|
436
|
+
res.statusCode =
|
|
437
|
+
result.status;
|
|
438
|
+
res.setHeader(
|
|
439
|
+
"Location",
|
|
440
|
+
result.url.href
|
|
441
|
+
);
|
|
442
|
+
res.setHeader(
|
|
443
|
+
"Cache-Control",
|
|
444
|
+
"no-store"
|
|
445
|
+
);
|
|
446
|
+
|
|
447
|
+
if (
|
|
448
|
+
req.method === "HEAD"
|
|
449
|
+
) {
|
|
450
|
+
res.end();
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
res.end();
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export async function sendMiddlewareResponse(
|
|
458
|
+
req: http.IncomingMessage,
|
|
459
|
+
res: http.ServerResponse,
|
|
460
|
+
response: Response
|
|
461
|
+
): Promise<void> {
|
|
462
|
+
res.statusCode =
|
|
463
|
+
response.status;
|
|
464
|
+
|
|
465
|
+
response.headers.forEach(
|
|
466
|
+
(value, key) => {
|
|
467
|
+
res.setHeader(
|
|
468
|
+
key,
|
|
469
|
+
value
|
|
470
|
+
);
|
|
471
|
+
}
|
|
472
|
+
);
|
|
473
|
+
|
|
474
|
+
const getSetCookie =
|
|
475
|
+
(
|
|
476
|
+
response.headers as Headers & {
|
|
477
|
+
getSetCookie?: () => string[];
|
|
478
|
+
}
|
|
479
|
+
).getSetCookie;
|
|
480
|
+
|
|
481
|
+
if (
|
|
482
|
+
typeof getSetCookie ===
|
|
483
|
+
"function"
|
|
484
|
+
) {
|
|
485
|
+
const cookies =
|
|
486
|
+
getSetCookie.call(
|
|
487
|
+
response.headers
|
|
488
|
+
);
|
|
489
|
+
|
|
490
|
+
if (
|
|
491
|
+
cookies.length > 0
|
|
492
|
+
) {
|
|
493
|
+
res.setHeader(
|
|
494
|
+
"Set-Cookie",
|
|
495
|
+
cookies
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
if (
|
|
501
|
+
req.method === "HEAD" ||
|
|
502
|
+
response.body === null
|
|
503
|
+
) {
|
|
504
|
+
res.end();
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
const body =
|
|
509
|
+
Buffer.from(
|
|
510
|
+
await response.arrayBuffer()
|
|
511
|
+
);
|
|
512
|
+
|
|
513
|
+
if (
|
|
514
|
+
!res.hasHeader(
|
|
515
|
+
"Content-Length"
|
|
516
|
+
)
|
|
517
|
+
) {
|
|
518
|
+
res.setHeader(
|
|
519
|
+
"Content-Length",
|
|
520
|
+
body.length
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
res.end(
|
|
525
|
+
body
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function matchPathPattern(
|
|
530
|
+
pathname: string,
|
|
531
|
+
pattern: string
|
|
532
|
+
): boolean {
|
|
533
|
+
if (
|
|
534
|
+
pattern === "*" ||
|
|
535
|
+
pattern === "/:path*"
|
|
536
|
+
) {
|
|
537
|
+
return true;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
if (
|
|
541
|
+
!pattern.startsWith(
|
|
542
|
+
"/"
|
|
543
|
+
)
|
|
544
|
+
) {
|
|
545
|
+
throw new Error(
|
|
546
|
+
`BCP Framework: middleware matcher "${pattern}" must start with "/".`
|
|
547
|
+
);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
const escaped =
|
|
551
|
+
pattern
|
|
552
|
+
.split("/")
|
|
553
|
+
.filter(
|
|
554
|
+
Boolean
|
|
555
|
+
)
|
|
556
|
+
.map(
|
|
557
|
+
(segment) => {
|
|
558
|
+
if (
|
|
559
|
+
segment === "*" ||
|
|
560
|
+
/^:[A-Za-z_][A-Za-z0-9_]*\*$/.test(
|
|
561
|
+
segment
|
|
562
|
+
)
|
|
563
|
+
) {
|
|
564
|
+
return "(?:.*)?";
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
if (
|
|
568
|
+
/^:[A-Za-z_][A-Za-z0-9_]*$/.test(
|
|
569
|
+
segment
|
|
570
|
+
)
|
|
571
|
+
) {
|
|
572
|
+
return "[^/]+";
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
return escapeRegExp(
|
|
576
|
+
segment
|
|
577
|
+
);
|
|
578
|
+
}
|
|
579
|
+
);
|
|
580
|
+
|
|
581
|
+
if (
|
|
582
|
+
escaped.length === 0
|
|
583
|
+
) {
|
|
584
|
+
return pathname === "/";
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
const source =
|
|
588
|
+
`^/${escaped.join("/")}/?$`;
|
|
589
|
+
|
|
590
|
+
return new RegExp(
|
|
591
|
+
source
|
|
592
|
+
).test(
|
|
593
|
+
pathname
|
|
594
|
+
);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
function createCookieStore(
|
|
598
|
+
cookieHeader: string | null
|
|
599
|
+
): MiddlewareCookieStore {
|
|
600
|
+
const values =
|
|
601
|
+
new Map<string, string>();
|
|
602
|
+
|
|
603
|
+
if (cookieHeader) {
|
|
604
|
+
for (
|
|
605
|
+
const part
|
|
606
|
+
of cookieHeader.split(";")
|
|
607
|
+
) {
|
|
608
|
+
const separator =
|
|
609
|
+
part.indexOf("=");
|
|
610
|
+
|
|
611
|
+
if (
|
|
612
|
+
separator < 0
|
|
613
|
+
) {
|
|
614
|
+
continue;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
const name =
|
|
618
|
+
part
|
|
619
|
+
.slice(
|
|
620
|
+
0,
|
|
621
|
+
separator
|
|
622
|
+
)
|
|
623
|
+
.trim();
|
|
624
|
+
const rawValue =
|
|
625
|
+
part
|
|
626
|
+
.slice(
|
|
627
|
+
separator + 1
|
|
628
|
+
)
|
|
629
|
+
.trim();
|
|
630
|
+
|
|
631
|
+
if (!name) {
|
|
632
|
+
continue;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
try {
|
|
636
|
+
values.set(
|
|
637
|
+
name,
|
|
638
|
+
decodeURIComponent(
|
|
639
|
+
rawValue
|
|
640
|
+
)
|
|
641
|
+
);
|
|
642
|
+
} catch {
|
|
643
|
+
values.set(
|
|
644
|
+
name,
|
|
645
|
+
rawValue
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
return {
|
|
652
|
+
get(name) {
|
|
653
|
+
return values.get(
|
|
654
|
+
name
|
|
655
|
+
) ?? null;
|
|
656
|
+
},
|
|
657
|
+
has(name) {
|
|
658
|
+
return values.has(
|
|
659
|
+
name
|
|
660
|
+
);
|
|
661
|
+
},
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
function mergeHeaders(
|
|
666
|
+
base: Headers,
|
|
667
|
+
additions: Headers
|
|
668
|
+
): Headers {
|
|
669
|
+
const result =
|
|
670
|
+
new Headers(
|
|
671
|
+
base
|
|
672
|
+
);
|
|
673
|
+
|
|
674
|
+
additions.forEach(
|
|
675
|
+
(value, key) => {
|
|
676
|
+
result.set(
|
|
677
|
+
key,
|
|
678
|
+
value
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
);
|
|
682
|
+
|
|
683
|
+
return result;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
function isFrameworkInternalPath(
|
|
687
|
+
pathname: string
|
|
688
|
+
): boolean {
|
|
689
|
+
return (
|
|
690
|
+
pathname === "/_bcp" ||
|
|
691
|
+
pathname.startsWith(
|
|
692
|
+
"/_bcp/"
|
|
693
|
+
)
|
|
694
|
+
);
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
function escapeRegExp(
|
|
698
|
+
value: string
|
|
699
|
+
): string {
|
|
700
|
+
return value.replace(
|
|
701
|
+
/[.*+?^${}()|[\]\\]/g,
|
|
702
|
+
"\\$&"
|
|
703
|
+
);
|
|
704
|
+
}
|