@fluojs/platform-express 1.0.0-beta.4 → 1.0.0-beta.6
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 +1 -1
- package/README.md +1 -1
- package/dist/adapter.d.ts +1 -0
- package/dist/adapter.d.ts.map +1 -1
- package/dist/adapter.js +79 -98
- package/package.json +3 -3
package/README.ko.md
CHANGED
|
@@ -73,7 +73,7 @@ const adapter = createExpressAdapter(
|
|
|
73
73
|
### 안전한 fallback을 포함한 Native Route Registration
|
|
74
74
|
이제 어댑터는 의미 보존이 가능한 명시적 HTTP 메서드 라우트를 Express Router에 사전 등록하면서도, 실제 요청 처리는 계속 공유 fluo dispatcher를 통해 수행합니다.
|
|
75
75
|
|
|
76
|
-
의미 보존이 가능한 unversioned route에서는 Express가 미리 고른 descriptor와 params를 공유 dispatcher에 전달하므로 duplicate route matching
|
|
76
|
+
의미 보존이 가능한 unversioned route에서는 Express가 미리 고른 descriptor와 params를 공유 dispatcher에 전달하므로 singleton-safe handler는 dispatcher fast path에서 완료될 수 있고 그 밖의 handler는 duplicate route matching 없이 fallback되며, guards, interceptors, observers, body parsing, raw body 캡처, SSE, 오류 응답은 기존과 같은 framework-owned 실행 경로를 유지합니다.
|
|
77
77
|
|
|
78
78
|
어댑터가 native handoff를 붙인 뒤 app middleware가 framework request의 method 또는 path를 rewrite하면 dispatcher는 그 handoff를 stale로 보고 원래 Express match를 재사용하지 않고 rewrite된 요청을 다시 매칭합니다.
|
|
79
79
|
|
package/README.md
CHANGED
|
@@ -73,7 +73,7 @@ const adapter = createExpressAdapter(
|
|
|
73
73
|
### Native Route Registration with Safe Fallback
|
|
74
74
|
The adapter now pre-registers semantically safe Express Router handlers for explicit HTTP methods and still dispatches those requests through the shared fluo dispatcher.
|
|
75
75
|
|
|
76
|
-
For semantically safe unversioned routes, Express hands the pre-matched descriptor and params to the shared dispatcher so duplicate route matching
|
|
76
|
+
For semantically safe unversioned routes, Express hands the pre-matched descriptor and params to the shared dispatcher so eligible singleton-safe handlers can complete on the dispatcher fast path and other handlers can fall back without duplicate route matching, while guards, interceptors, observers, body parsing, raw body capture, SSE, and error responses stay on the same framework-owned execution path.
|
|
77
77
|
|
|
78
78
|
If app middleware rewrites the framework request method or path after the adapter attaches a native handoff, the dispatcher treats that handoff as stale and rematches the rewritten request instead of reusing the original Express match.
|
|
79
79
|
|
package/dist/adapter.d.ts
CHANGED
package/dist/adapter.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
|
package/dist/adapter.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { createServer as createHttpServer } from 'node:http';
|
|
2
2
|
import { createServer as createHttpsServer } from 'node:https';
|
|
3
3
|
import { Readable } from 'node:stream';
|
|
4
|
-
import { URL } from 'node:url';
|
|
5
4
|
import express from 'express';
|
|
6
5
|
import { BadRequestException, createServerBackedHttpAdapterRealtimeCapability, createErrorResponse, HttpException, InternalServerErrorException, PayloadTooLargeException } from '@fluojs/http';
|
|
7
6
|
import { attachFrameworkRequestNativeRouteHandoff, bindRawRequestNativeRouteHandoff, consumeRawRequestNativeRouteHandoff, isRoutePathNormalizationSensitive } from '@fluojs/http/internal';
|
|
8
7
|
import { createNodeShutdownSignalRegistration, defaultNodeShutdownSignals } from '@fluojs/runtime/node';
|
|
8
|
+
import { cloneRequestHeaders, createDeferredFrameworkRequestShell, createMemoizedAsyncValue, createRequestSignal, normalizePrimaryContentType, parseQueryParamsFromSearch, resolveAbsoluteRequestUrl, resolveRequestIdFromHeaders, snapshotSimpleQueryRecord, splitRawRequestUrl } from '@fluojs/runtime/internal-node';
|
|
9
9
|
import { parseMultipart } from '@fluojs/runtime/web';
|
|
10
10
|
import { bootstrapHttpAdapterApplication, runHttpAdapterApplication } from '@fluojs/runtime/internal/http-adapter';
|
|
11
11
|
import { dispatchWithRequestResponseFactory } from '@fluojs/runtime/internal/request-response-factory';
|
|
@@ -131,14 +131,12 @@ export class ExpressHttpApplicationAdapter {
|
|
|
131
131
|
return;
|
|
132
132
|
}
|
|
133
133
|
const nativeMethod = request.method.toUpperCase();
|
|
134
|
-
const requestPath =
|
|
134
|
+
const requestPath = splitRawRequestUrl(request.originalUrl || request.url || '/').path;
|
|
135
135
|
const descriptor = route.descriptorsByMethod[nativeMethod];
|
|
136
136
|
const params = normalizeNativeRouteParams(request.params);
|
|
137
137
|
if (descriptor && !isRoutePathNormalizationSensitive(requestPath) && !hasNativeRouteParamSeparators(params)) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
params
|
|
141
|
-
});
|
|
138
|
+
void this.handleNativeRouteRequest(descriptor, params, request, response);
|
|
139
|
+
return;
|
|
142
140
|
}
|
|
143
141
|
void this.handleRequest(request, response);
|
|
144
142
|
});
|
|
@@ -154,6 +152,42 @@ export class ExpressHttpApplicationAdapter {
|
|
|
154
152
|
rawResponse: response
|
|
155
153
|
});
|
|
156
154
|
}
|
|
155
|
+
async handleNativeRouteRequest(descriptor, params, request, response) {
|
|
156
|
+
const dispatcher = this.dispatcher;
|
|
157
|
+
if (!dispatcher?.dispatchNativeRoute) {
|
|
158
|
+
bindRawRequestNativeRouteHandoff(request, {
|
|
159
|
+
descriptor,
|
|
160
|
+
params
|
|
161
|
+
});
|
|
162
|
+
await this.handleRequest(request, response);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const factory = this.requestResponseFactory;
|
|
166
|
+
const frameworkResponse = factory.createResponse(response, request);
|
|
167
|
+
const signal = factory.createRequestSignal(response);
|
|
168
|
+
try {
|
|
169
|
+
const frameworkRequest = attachFrameworkRequestNativeRouteHandoff(await factory.createRequest(request, signal), {
|
|
170
|
+
descriptor,
|
|
171
|
+
params
|
|
172
|
+
});
|
|
173
|
+
await factory.materializeRequest?.(frameworkRequest);
|
|
174
|
+
const handled = await dispatcher.dispatchNativeRoute({
|
|
175
|
+
descriptor,
|
|
176
|
+
params
|
|
177
|
+
}, frameworkRequest, frameworkResponse);
|
|
178
|
+
if (!handled && !frameworkResponse.committed) {
|
|
179
|
+
await dispatcher.dispatch(frameworkRequest, frameworkResponse);
|
|
180
|
+
}
|
|
181
|
+
if (!frameworkResponse.committed) {
|
|
182
|
+
await frameworkResponse.send(undefined);
|
|
183
|
+
}
|
|
184
|
+
} catch (error) {
|
|
185
|
+
if (signal.aborted || frameworkResponse.committed) {
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
await factory.writeErrorResponse(error, frameworkResponse, factory.resolveRequestId(request));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
157
191
|
}
|
|
158
192
|
function resolveDispatcherRouteDescriptors(dispatcher) {
|
|
159
193
|
return dispatcher.describeRoutes?.() ?? [];
|
|
@@ -228,6 +262,9 @@ function createExpressRequestResponseFactory(multipartOptions, maxBodySize = DEF
|
|
|
228
262
|
createResponse(response) {
|
|
229
263
|
return createFrameworkResponse(response);
|
|
230
264
|
},
|
|
265
|
+
async materializeRequest(request) {
|
|
266
|
+
await materializeFrameworkRequestBody(request);
|
|
267
|
+
},
|
|
231
268
|
resolveRequestId(request) {
|
|
232
269
|
return resolveRequestIdFromHeaders(request.headers);
|
|
233
270
|
},
|
|
@@ -374,43 +411,40 @@ function createFrameworkResponseStream(response) {
|
|
|
374
411
|
}
|
|
375
412
|
async function createFrameworkRequest(request, signal, multipartOptions, maxBodySize = DEFAULT_MAX_BODY_SIZE, preserveRawBody = false) {
|
|
376
413
|
const rawUrl = request.originalUrl || request.url || '/';
|
|
377
|
-
const
|
|
378
|
-
const headers = normalizeHeaders(request.headers);
|
|
379
|
-
const
|
|
380
|
-
const
|
|
381
|
-
|
|
382
|
-
let
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
414
|
+
const urlParts = splitRawRequestUrl(rawUrl);
|
|
415
|
+
const headers = normalizeHeaders(cloneRequestHeaders(request.headers));
|
|
416
|
+
const querySnapshot = snapshotSimpleQueryRecord(request.query);
|
|
417
|
+
const contentType = normalizePrimaryContentType(headers['content-type']);
|
|
418
|
+
const isMultipart = contentType === 'multipart/form-data';
|
|
419
|
+
let frameworkRequest;
|
|
420
|
+
const materializeBody = createMemoizedAsyncValue(async () => {
|
|
421
|
+
if (isMultipart) {
|
|
422
|
+
const parsed = await parseMultipartRequest(request, {
|
|
423
|
+
...multipartOptions,
|
|
424
|
+
maxTotalSize: multipartOptions?.maxTotalSize ?? maxBodySize
|
|
425
|
+
});
|
|
426
|
+
frameworkRequest.body = parsed.fields;
|
|
427
|
+
frameworkRequest.files = parsed.files;
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
392
430
|
const bodyResult = await readRequestBody(request, headers['content-type'], maxBodySize, preserveRawBody);
|
|
393
|
-
body = bodyResult.body;
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
431
|
+
frameworkRequest.body = bodyResult.body;
|
|
432
|
+
if (bodyResult.rawBody) {
|
|
433
|
+
frameworkRequest.rawBody = bodyResult.rawBody;
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
frameworkRequest = createDeferredFrameworkRequestShell({
|
|
437
|
+
cookieHeader: headers.cookie,
|
|
399
438
|
headers,
|
|
439
|
+
materializeBody,
|
|
400
440
|
method: request.method,
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
441
|
+
path: urlParts.path,
|
|
442
|
+
query: querySnapshot,
|
|
443
|
+
queryFactory: () => parseQueryParamsFromSearch(urlParts.search),
|
|
404
444
|
raw: request,
|
|
405
445
|
signal,
|
|
406
|
-
url:
|
|
407
|
-
};
|
|
408
|
-
if (files) {
|
|
409
|
-
frameworkRequest.files = files;
|
|
410
|
-
}
|
|
411
|
-
if (rawBody) {
|
|
412
|
-
frameworkRequest.rawBody = rawBody;
|
|
413
|
-
}
|
|
446
|
+
url: urlParts.path + urlParts.search
|
|
447
|
+
});
|
|
414
448
|
const nativeRouteHandoff = consumeRawRequestNativeRouteHandoff(request);
|
|
415
449
|
return nativeRouteHandoff ? attachFrameworkRequestNativeRouteHandoff(frameworkRequest, nativeRouteHandoff) : frameworkRequest;
|
|
416
450
|
}
|
|
@@ -446,7 +480,7 @@ async function parseMultipartRequest(request, options = {}) {
|
|
|
446
480
|
body: Readable.toWeb(request),
|
|
447
481
|
headers: normalizeHeaders(request.headers),
|
|
448
482
|
method: request.method,
|
|
449
|
-
url:
|
|
483
|
+
url: resolveAbsoluteRequestUrl(request.url)
|
|
450
484
|
}, options);
|
|
451
485
|
} catch (error) {
|
|
452
486
|
if (isExpressMultipartTooLargeError(error)) {
|
|
@@ -503,57 +537,6 @@ function normalizeHeaders(headers) {
|
|
|
503
537
|
}
|
|
504
538
|
return normalized;
|
|
505
539
|
}
|
|
506
|
-
function parseQueryParams(searchParams) {
|
|
507
|
-
const query = {};
|
|
508
|
-
for (const [key, value] of searchParams.entries()) {
|
|
509
|
-
const current = query[key];
|
|
510
|
-
if (current === undefined) {
|
|
511
|
-
query[key] = value;
|
|
512
|
-
continue;
|
|
513
|
-
}
|
|
514
|
-
if (Array.isArray(current)) {
|
|
515
|
-
current.push(value);
|
|
516
|
-
continue;
|
|
517
|
-
}
|
|
518
|
-
query[key] = [current, value];
|
|
519
|
-
}
|
|
520
|
-
return query;
|
|
521
|
-
}
|
|
522
|
-
function parseCookieHeader(cookieHeader) {
|
|
523
|
-
if (!cookieHeader) {
|
|
524
|
-
return {};
|
|
525
|
-
}
|
|
526
|
-
return Object.fromEntries(cookieHeader.split(';').map(pair => pair.trim()).filter(Boolean).map(pair => {
|
|
527
|
-
const index = pair.indexOf('=');
|
|
528
|
-
if (index === -1) {
|
|
529
|
-
return [pair.trim(), ''];
|
|
530
|
-
}
|
|
531
|
-
const rawValue = pair.slice(index + 1).trim();
|
|
532
|
-
try {
|
|
533
|
-
return [pair.slice(0, index).trim(), decodeURIComponent(rawValue)];
|
|
534
|
-
} catch {
|
|
535
|
-
return [pair.slice(0, index).trim(), rawValue];
|
|
536
|
-
}
|
|
537
|
-
}));
|
|
538
|
-
}
|
|
539
|
-
function createRequestSignal(response) {
|
|
540
|
-
const controller = new AbortController();
|
|
541
|
-
const abort = reason => {
|
|
542
|
-
if (!controller.signal.aborted) {
|
|
543
|
-
controller.abort(new Error(reason));
|
|
544
|
-
}
|
|
545
|
-
};
|
|
546
|
-
response.once('close', () => {
|
|
547
|
-
if (!response.writableEnded) {
|
|
548
|
-
abort('Response closed before response commit.');
|
|
549
|
-
}
|
|
550
|
-
});
|
|
551
|
-
return controller.signal;
|
|
552
|
-
}
|
|
553
|
-
function resolveRequestIdFromHeaders(headers) {
|
|
554
|
-
const requestId = headers['x-request-id'] ?? headers['x-correlation-id'];
|
|
555
|
-
return Array.isArray(requestId) ? requestId[0] : requestId;
|
|
556
|
-
}
|
|
557
540
|
function createExpressServer(httpsOptions, app) {
|
|
558
541
|
return httpsOptions ? createHttpsServer(httpsOptions, app) : createHttpServer(app);
|
|
559
542
|
}
|
|
@@ -724,8 +707,8 @@ async function readRequestBody(request, contentType, maxBodySize = DEFAULT_MAX_B
|
|
|
724
707
|
rawBody: preserveRawBody ? rawBody : undefined
|
|
725
708
|
};
|
|
726
709
|
}
|
|
727
|
-
const primaryContentType =
|
|
728
|
-
if (
|
|
710
|
+
const primaryContentType = normalizePrimaryContentType(contentType);
|
|
711
|
+
if (primaryContentType === 'application/json') {
|
|
729
712
|
try {
|
|
730
713
|
return {
|
|
731
714
|
body: JSON.parse(bodyText),
|
|
@@ -735,7 +718,7 @@ async function readRequestBody(request, contentType, maxBodySize = DEFAULT_MAX_B
|
|
|
735
718
|
throw new BadRequestException('Request body contains invalid JSON.');
|
|
736
719
|
}
|
|
737
720
|
}
|
|
738
|
-
if (
|
|
721
|
+
if (primaryContentType === 'application/x-www-form-urlencoded') {
|
|
739
722
|
return {
|
|
740
723
|
body: parseUrlEncodedBody(bodyText),
|
|
741
724
|
rawBody: preserveRawBody ? rawBody : undefined
|
|
@@ -754,11 +737,9 @@ function parseUrlEncodedBody(bodyText) {
|
|
|
754
737
|
}
|
|
755
738
|
return fields;
|
|
756
739
|
}
|
|
757
|
-
function
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
}
|
|
761
|
-
return headerValue;
|
|
740
|
+
async function materializeFrameworkRequestBody(request) {
|
|
741
|
+
await request.materializeBody?.();
|
|
742
|
+
delete request.materializeBody;
|
|
762
743
|
}
|
|
763
744
|
function setMultiValue(target, key, value) {
|
|
764
745
|
const existing = target[key];
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"platform",
|
|
9
9
|
"server"
|
|
10
10
|
],
|
|
11
|
-
"version": "1.0.0-beta.
|
|
11
|
+
"version": "1.0.0-beta.6",
|
|
12
12
|
"private": false,
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"repository": {
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"express": "^5.1.0",
|
|
39
|
-
"@fluojs/http": "^1.0.0-beta.
|
|
40
|
-
"@fluojs/runtime": "^1.0.0-beta.
|
|
39
|
+
"@fluojs/http": "^1.0.0-beta.7",
|
|
40
|
+
"@fluojs/runtime": "^1.0.0-beta.8"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/express": "^5.0.3",
|