acrylblends 0.6.3 → 0.7.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.md +4 -3
- package/docs/framework/README.md +2 -2
- package/docs/framework/UPSTREAM.md +1 -1
- package/docs/framework/guides/jsx.md +51 -1
- package/docs/framework/helpers/ssg.md +3 -6
- package/docs/framework/middleware/builtin/jsx-renderer.md +0 -3
- package/docs/framework/upstream.json +2 -2
- package/lib/accepts.d.ts +1 -1
- package/lib/acryl-base.d.ts +1 -1
- package/lib/adapter.d.ts +1 -1
- package/lib/{app-wFwpg-bt.d.ts → app-D8riatvv.d.ts} +1 -1
- package/lib/{base-ddiVmiE7.js → base-NSN_SNv-.js} +1 -0
- package/lib/basic-auth.d.ts +1 -1
- package/lib/bearer-auth.d.ts +1 -1
- package/lib/body-limit.d.ts +1 -1
- package/lib/cache.d.ts +1 -1
- package/lib/cache.js +4 -4
- package/lib/{client-BHTr318g.js → client-DDLXwhBo.js} +2 -125
- package/lib/client.d.ts +2 -2
- package/lib/client.js +2 -1
- package/lib/combine.d.ts +1 -1
- package/lib/{components-DYZdxJIJ.js → components-JXVm45kK.js} +1 -1
- package/lib/{components-Ce5FRyHU.js → components-cEW3ovK0.js} +3 -3
- package/lib/compress.d.ts +1 -1
- package/lib/conninfo.d.ts +2 -2
- package/lib/{context-DVQBjuns.d.ts → context-DS3fYyG-.d.ts} +1 -1
- package/lib/context-storage.d.ts +1 -1
- package/lib/cookie.d.ts +1 -1
- package/lib/cors.d.ts +1 -1
- package/lib/csrf.d.ts +1 -1
- package/lib/dev.d.ts +2 -2
- package/lib/etag.d.ts +1 -1
- package/lib/factory.d.ts +2 -2
- package/lib/{hooks-Bq5q9IMl.js → hooks-w72iLeFR.js} +6 -6
- package/lib/{index-CUTfU69R.d.ts → index-Bb7YJKCq.d.ts} +2 -2
- package/lib/{index-CsvB-F9j.d.ts → index-BvFh1Gfx.d.ts} +1 -1
- package/lib/{index-Cqcdluyn.d.ts → index-CTy4N7ng.d.ts} +2 -2
- package/lib/index.d.ts +4 -4
- package/lib/ip-restriction.d.ts +2 -2
- package/lib/jsx/dom/client.js +1 -1
- package/lib/jsx/dom/jsx-dev-runtime.js +1 -1
- package/lib/jsx/dom/jsx-runtime.js +1 -1
- package/lib/jsx/dom/server.js +2 -2
- package/lib/jsx/dom.js +4 -4
- package/lib/jsx/jsx-dev-runtime.js +1 -1
- package/lib/jsx/jsx-runtime.js +1 -1
- package/lib/jsx/streaming.js +1 -1
- package/lib/{jsx-dev-runtime-kAhR_4C7.js → jsx-dev-runtime-CWLRA2F3.js} +2 -2
- package/lib/jsx-renderer.d.ts +75 -0
- package/lib/jsx-renderer.js +99 -0
- package/lib/jsx.js +4 -4
- package/lib/jwk.d.ts +1 -1
- package/lib/jwt.d.ts +1 -1
- package/lib/language.d.ts +1 -1
- package/lib/logger.d.ts +1 -1
- package/lib/loopback-only.d.ts +1 -1
- package/lib/method-not-allowed.d.ts +2 -2
- package/lib/method-override.d.ts +2 -2
- package/lib/mount.d.ts +1 -1
- package/lib/node-server/conninfo.d.ts +1 -1
- package/lib/node-server/register.d.ts +1 -0
- package/lib/node-server/register.js +73 -0
- package/lib/node-server/serve-static.d.ts +1 -1
- package/lib/node-server/serve-static.js +1 -1
- package/lib/node-server.d.ts +1 -1
- package/lib/node-server.js +1 -1
- package/lib/powered-by.d.ts +1 -1
- package/lib/pretty-json.d.ts +1 -1
- package/lib/quick.d.ts +1 -1
- package/lib/request-id.d.ts +1 -1
- package/lib/request.d.ts +1 -1
- package/lib/route.d.ts +1 -1
- package/lib/schema-validator.d.ts +1 -1
- package/lib/secure-headers.d.ts +1 -1
- package/lib/{serve-static-Cw23shXv.js → serve-static-B14MF1Va.js} +1 -0
- package/lib/serve-static.d.ts +1 -1
- package/lib/ssg-BwjcA-Ge.js +389 -0
- package/lib/ssg.d.ts +156 -0
- package/lib/ssg.js +2 -0
- package/lib/streaming.d.ts +1 -1
- package/lib/testing.d.ts +3 -3
- package/lib/testing.js +1 -1
- package/lib/timeout.d.ts +1 -1
- package/lib/timing.d.ts +1 -1
- package/lib/tiny.d.ts +1 -1
- package/lib/trailing-slash.d.ts +1 -1
- package/lib/{types-nEL8VPDC.d.ts → types-Dv_nV2cv.d.ts} +1 -1
- package/lib/{types-CQiGmsWW.d.ts → types-zNxyEpG2.d.ts} +2 -2
- package/lib/types.d.ts +1 -1
- package/lib/utils/body.d.ts +1 -1
- package/lib/utils/ipaddr.d.ts +1 -1
- package/lib/utils-Cx61GFMC.js +125 -0
- package/lib/validator.d.ts +1 -1
- package/lib/ws.d.ts +1 -1
- package/package.json +13 -1
- package/plugins/acryl-inspect/upstream.json +1 -1
- package/plugins/acryl-node-server/src/register.ts +86 -0
- package/plugins/acryl-node-server/upstream.json +5 -3
- package/plugins/acryl-router/src/core/helper/ssg/index.ts +14 -0
- package/plugins/acryl-router/src/core/helper/ssg/middleware.ts +83 -0
- package/plugins/acryl-router/src/core/helper/ssg/plugins.ts +72 -0
- package/plugins/acryl-router/src/core/helper/ssg/ssg.ts +471 -0
- package/plugins/acryl-router/src/core/helper/ssg/utils.ts +118 -0
- package/plugins/acryl-router/src/core/jsx/dom/render.ts +6 -6
- package/plugins/acryl-router/src/core/middleware/cache/index.ts +4 -4
- package/plugins/acryl-router/src/core/middleware/jsx-renderer/index.ts +162 -0
- package/plugins/acryl-router/src/helpers/index.ts +1 -0
- package/plugins/acryl-router/src/middleware/index.ts +1 -0
- package/plugins/acryl-router/upstream.json +2 -2
- package/plugins/acryl-router-http/upstream.json +1 -1
- package/plugins/acryl-state/upstream.json +1 -1
- package/plugins/desktop/main.ts +4 -1
- package/plugins/desktop/upstream.json +1 -1
- package/plugins/desktop-web/main.ts +3 -1
- package/plugins/desktop-web/upstream.json +1 -1
- package/plugins/extensions/resolve.ts +4 -0
- package/shared/AGENTS.core.md +3 -0
- package/templates/agent/package.json +7 -3
- package/templates/agent/tsconfig.json +10 -2
- package/templates/blank/package.json +7 -3
- package/templates/blank/src/about.tsx +14 -0
- package/templates/blank/src/routes.ts +2 -0
- package/templates/blank/test/app.test.ts +15 -0
- package/templates/blank/tsconfig.json +3 -1
- package/templates/todo/package.json +7 -3
- package/templates/todo/tsconfig.json +3 -1
- package/templates/todo/upstream.json +1 -1
- package/plugins/acryl-inspect/tests/report.spec.ts +0 -69
- package/plugins/acryl-inspect/tests/service.spec.ts +0 -121
- package/plugins/acryl-node-server/tests/adapter/app.ts +0 -76
- package/plugins/acryl-node-server/tests/adapter/assets/.static/plain.txt +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/favicon.ico +0 -0
- package/plugins/acryl-node-server/tests/adapter/assets/secret.txt +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static/acryl.html +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static/admin/secret.txt +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static/data.json +0 -5
- package/plugins/acryl-node-server/tests/adapter/assets/static/extensionless +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static/foo..bar.txt +0 -0
- package/plugins/acryl-node-server/tests/adapter/assets/static/index.html +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static/plain.txt +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static-with-context-path/plain.txt +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.bin +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.bin.br +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt.br +0 -1
- package/plugins/acryl-node-server/tests/adapter/assets/static-with-precompressed/hello.txt.zst +0 -1
- package/plugins/acryl-node-server/tests/adapter/conninfo.test.ts +0 -34
- package/plugins/acryl-node-server/tests/adapter/content-length.test.ts +0 -248
- package/plugins/acryl-node-server/tests/adapter/early-hints.test.ts +0 -457
- package/plugins/acryl-node-server/tests/adapter/fixtures/keys/agent1-cert.pem +0 -23
- package/plugins/acryl-node-server/tests/adapter/fixtures/keys/agent1-key.pem +0 -27
- package/plugins/acryl-node-server/tests/adapter/headers.test.ts +0 -252
- package/plugins/acryl-node-server/tests/adapter/helpers/request.ts +0 -190
- package/plugins/acryl-node-server/tests/adapter/listener.test.ts +0 -727
- package/plugins/acryl-node-server/tests/adapter/request-client-disconnect.test.ts +0 -189
- package/plugins/acryl-node-server/tests/adapter/request.test.ts +0 -1230
- package/plugins/acryl-node-server/tests/adapter/response.test.ts +0 -285
- package/plugins/acryl-node-server/tests/adapter/serve-static.test.ts +0 -849
- package/plugins/acryl-node-server/tests/adapter/server-socket.test.ts +0 -790
- package/plugins/acryl-node-server/tests/adapter/server.test.ts +0 -1312
- package/plugins/acryl-node-server/tests/adapter/setup.ts +0 -16
- package/plugins/acryl-node-server/tests/adapter/url.test.ts +0 -76
- package/plugins/acryl-node-server/tests/adapter/utils/response.test.ts +0 -23
- package/plugins/acryl-node-server/tests/adapter/utils/stream.test.ts +0 -75
- package/plugins/acryl-node-server/tests/adapter/utils.test.ts +0 -235
- package/plugins/acryl-node-server/tests/adapter/websocket.test.ts +0 -260
- package/plugins/acryl-node-server/tests/server.spec.ts +0 -141
- package/plugins/acryl-router/src/core/app.test.ts +0 -3833
- package/plugins/acryl-router/src/core/client/client.test.ts +0 -2313
- package/plugins/acryl-router/src/core/client/types.test.ts +0 -149
- package/plugins/acryl-router/src/core/client/utils.test.ts +0 -405
- package/plugins/acryl-router/src/core/compose.test.ts +0 -751
- package/plugins/acryl-router/src/core/context.test.ts +0 -629
- package/plugins/acryl-router/src/core/helper/accepts/accepts.test.ts +0 -344
- package/plugins/acryl-router/src/core/helper/adapter/index.test.ts +0 -55
- package/plugins/acryl-router/src/core/helper/cookie/index.test.ts +0 -510
- package/plugins/acryl-router/src/core/helper/css/common.case.test.tsx +0 -506
- package/plugins/acryl-router/src/core/helper/css/index.test.tsx +0 -678
- package/plugins/acryl-router/src/core/helper/dev/index.test.ts +0 -181
- package/plugins/acryl-router/src/core/helper/factory/index.test.ts +0 -434
- package/plugins/acryl-router/src/core/helper/html/index.test.ts +0 -78
- package/plugins/acryl-router/src/core/helper/proxy/index.test.ts +0 -356
- package/plugins/acryl-router/src/core/helper/route/index.test.ts +0 -259
- package/plugins/acryl-router/src/core/helper/streaming/sse.test.tsx +0 -557
- package/plugins/acryl-router/src/core/helper/streaming/stream.test.ts +0 -128
- package/plugins/acryl-router/src/core/helper/streaming/text.test.ts +0 -34
- package/plugins/acryl-router/src/core/helper/testing/index.test.ts +0 -42
- package/plugins/acryl-router/src/core/helper/websocket/index.test.ts +0 -124
- package/plugins/acryl-router/src/core/http-exception.test.ts +0 -45
- package/plugins/acryl-router/src/core/jsx/base.test.tsx +0 -97
- package/plugins/acryl-router/src/core/jsx/children.test.ts +0 -52
- package/plugins/acryl-router/src/core/jsx/components.test.tsx +0 -936
- package/plugins/acryl-router/src/core/jsx/context-isolation.test.ts +0 -655
- package/plugins/acryl-router/src/core/jsx/dom/client.test.tsx +0 -128
- package/plugins/acryl-router/src/core/jsx/dom/components.test.tsx +0 -330
- package/plugins/acryl-router/src/core/jsx/dom/context.test.tsx +0 -184
- package/plugins/acryl-router/src/core/jsx/dom/css.test.tsx +0 -149
- package/plugins/acryl-router/src/core/jsx/dom/hooks/index.test.tsx +0 -172
- package/plugins/acryl-router/src/core/jsx/dom/index.test.tsx +0 -3681
- package/plugins/acryl-router/src/core/jsx/dom/intrinsic-element/components.test.tsx +0 -1344
- package/plugins/acryl-router/src/core/jsx/dom/server.test.tsx +0 -199
- package/plugins/acryl-router/src/core/jsx/hooks/dom.test.tsx +0 -859
- package/plugins/acryl-router/src/core/jsx/hooks/string.test.tsx +0 -40
- package/plugins/acryl-router/src/core/jsx/index.test.tsx +0 -1744
- package/plugins/acryl-router/src/core/jsx/intrinsic-element/components.test.tsx +0 -666
- package/plugins/acryl-router/src/core/jsx/jsx-runtime.test.tsx +0 -85
- package/plugins/acryl-router/src/core/jsx/streaming.test.tsx +0 -1281
- package/plugins/acryl-router/src/core/jsx/utils.test.ts +0 -366
- package/plugins/acryl-router/src/core/middleware/basic-auth/index.test.ts +0 -434
- package/plugins/acryl-router/src/core/middleware/bearer-auth/index.test.ts +0 -1018
- package/plugins/acryl-router/src/core/middleware/body-limit/index.test.ts +0 -273
- package/plugins/acryl-router/src/core/middleware/cache/index.test.ts +0 -1211
- package/plugins/acryl-router/src/core/middleware/combine/index.test.ts +0 -355
- package/plugins/acryl-router/src/core/middleware/compress/index.test.ts +0 -535
- package/plugins/acryl-router/src/core/middleware/context-storage/index.test.ts +0 -43
- package/plugins/acryl-router/src/core/middleware/cors/index.test.ts +0 -532
- package/plugins/acryl-router/src/core/middleware/csrf/index.test.ts +0 -534
- package/plugins/acryl-router/src/core/middleware/etag/digest.test.ts +0 -21
- package/plugins/acryl-router/src/core/middleware/etag/index.test.ts +0 -503
- package/plugins/acryl-router/src/core/middleware/ip-restriction/index.test.ts +0 -217
- package/plugins/acryl-router/src/core/middleware/jwk/index.test.ts +0 -1135
- package/plugins/acryl-router/src/core/middleware/jwk/keys.test.json +0 -48
- package/plugins/acryl-router/src/core/middleware/jwt/index.test.ts +0 -802
- package/plugins/acryl-router/src/core/middleware/language/index.test.ts +0 -552
- package/plugins/acryl-router/src/core/middleware/logger/index.test.ts +0 -204
- package/plugins/acryl-router/src/core/middleware/method-not-allowed/index.test.ts +0 -292
- package/plugins/acryl-router/src/core/middleware/method-override/index.test.ts +0 -221
- package/plugins/acryl-router/src/core/middleware/mount/index.test.ts +0 -334
- package/plugins/acryl-router/src/core/middleware/powered-by/index.test.ts +0 -37
- package/plugins/acryl-router/src/core/middleware/pretty-json/index.test.ts +0 -218
- package/plugins/acryl-router/src/core/middleware/request-id/index.test.ts +0 -168
- package/plugins/acryl-router/src/core/middleware/secure-headers/index.test.ts +0 -671
- package/plugins/acryl-router/src/core/middleware/serve-static/index.test.ts +0 -450
- package/plugins/acryl-router/src/core/middleware/serve-static/path.test.ts +0 -50
- package/plugins/acryl-router/src/core/middleware/timeout/index.test.ts +0 -70
- package/plugins/acryl-router/src/core/middleware/timing/index.test.ts +0 -310
- package/plugins/acryl-router/src/core/middleware/trailing-slash/index.test.ts +0 -381
- package/plugins/acryl-router/src/core/preset/quick.test.ts +0 -42
- package/plugins/acryl-router/src/core/preset/tiny.test.ts +0 -42
- package/plugins/acryl-router/src/core/request.test.ts +0 -751
- package/plugins/acryl-router/src/core/router/common.case.test.ts +0 -1132
- package/plugins/acryl-router/src/core/router/linear-router/router.test.ts +0 -80
- package/plugins/acryl-router/src/core/router/pattern-router/router.test.ts +0 -46
- package/plugins/acryl-router/src/core/router/reg-exp-router/prepared-router.test.ts +0 -154
- package/plugins/acryl-router/src/core/router/reg-exp-router/router.test.ts +0 -265
- package/plugins/acryl-router/src/core/router/smart-router/router.test.ts +0 -13
- package/plugins/acryl-router/src/core/router/trie-router/node.test.ts +0 -896
- package/plugins/acryl-router/src/core/router/trie-router/router.test.ts +0 -8
- package/plugins/acryl-router/src/core/types.test.ts +0 -4134
- package/plugins/acryl-router/src/core/utils/accept.test.ts +0 -299
- package/plugins/acryl-router/src/core/utils/basic-auth.test.ts +0 -56
- package/plugins/acryl-router/src/core/utils/body.test.ts +0 -496
- package/plugins/acryl-router/src/core/utils/buffer.test.ts +0 -147
- package/plugins/acryl-router/src/core/utils/color.test.ts +0 -23
- package/plugins/acryl-router/src/core/utils/concurrent.test.ts +0 -69
- package/plugins/acryl-router/src/core/utils/cookie.test.ts +0 -460
- package/plugins/acryl-router/src/core/utils/crypto.test.ts +0 -43
- package/plugins/acryl-router/src/core/utils/encode.test.ts +0 -61
- package/plugins/acryl-router/src/core/utils/filepath.test.ts +0 -78
- package/plugins/acryl-router/src/core/utils/html.test.ts +0 -16
- package/plugins/acryl-router/src/core/utils/ipaddr.test.ts +0 -149
- package/plugins/acryl-router/src/core/utils/jwt/jwa.test.ts +0 -86
- package/plugins/acryl-router/src/core/utils/jwt/jwt.test.ts +0 -1788
- package/plugins/acryl-router/src/core/utils/mime.test.ts +0 -64
- package/plugins/acryl-router/src/core/utils/stream.test.ts +0 -212
- package/plugins/acryl-router/src/core/utils/types.test.ts +0 -295
- package/plugins/acryl-router/src/core/utils/url.test.ts +0 -384
- package/plugins/acryl-router/src/core/validator/utils.test.ts +0 -82
- package/plugins/acryl-router/src/core/validator/validator.test.ts +0 -1488
- package/plugins/acryl-router/tests/docs-examples.spec.ts +0 -152
- package/plugins/acryl-router/tests/jsx.spec.tsx +0 -63
- package/plugins/acryl-router/tests/live-install.spec.ts +0 -64
- package/plugins/acryl-router/tests/loader.spec.ts +0 -72
- package/plugins/acryl-router/tests/loopback-only.spec.ts +0 -80
- package/plugins/acryl-router/tests/no-dom/consumer.ts +0 -11
- package/plugins/acryl-router/tests/no-dom/tsconfig.json +0 -13
- package/plugins/acryl-router/tests/service.spec.ts +0 -426
- package/plugins/acryl-router/tests/shadow-state.spec.ts +0 -79
- package/plugins/acryl-router-http/tests/adapter.spec.ts +0 -174
- package/plugins/acryl-router-http/tests/stream.spec.ts +0 -133
- package/plugins/acryl-router-http/tests/surfaces.spec.ts +0 -101
- package/plugins/acryl-state/src/react.ts +0 -11
- package/plugins/acryl-state/tests/cell.spec.ts +0 -71
- package/plugins/acryl-state/tests/react.spec.ts +0 -39
- package/plugins/acryl-state/tests/service.spec.ts +0 -132
|
@@ -1,252 +0,0 @@
|
|
|
1
|
-
import type { IncomingMessage } from 'node:http'
|
|
2
|
-
import { Http2ServerRequest } from 'node:http2'
|
|
3
|
-
import type { ServerHttp2Stream } from 'node:http2'
|
|
4
|
-
import { Duplex } from 'node:stream'
|
|
5
|
-
import { inspect } from 'node:util'
|
|
6
|
-
import { GlobalHeaders, RequestHeaders, newHeadersFromIncoming } from '../../src/adapter/headers.ts'
|
|
7
|
-
import { newRequest, Request as LightweightRequest } from '../../src/adapter/request.ts'
|
|
8
|
-
|
|
9
|
-
// Compatibility cases adapted from srvx's Node header suite:
|
|
10
|
-
// https://github.com/h3js/srvx/blob/4052594e76d5ead2cc4c7cf8f7fa6d5ea9558a0a/test/node-headers.test.ts
|
|
11
|
-
|
|
12
|
-
const incoming = (rawHeaders: string[], headers: Record<string, unknown>): IncomingMessage =>
|
|
13
|
-
({ rawHeaders, headers }) as IncomingMessage
|
|
14
|
-
|
|
15
|
-
const incomingHttp2 = (
|
|
16
|
-
rawHeaders: string[],
|
|
17
|
-
headers: Record<string, string | string[]>
|
|
18
|
-
): Http2ServerRequest =>
|
|
19
|
-
new Http2ServerRequest(new Duplex() as ServerHttp2Stream, headers, {}, rawHeaders)
|
|
20
|
-
|
|
21
|
-
const lightweightHeaders = (request: IncomingMessage | Http2ServerRequest): GlobalHeaders =>
|
|
22
|
-
newHeadersFromIncoming(request)
|
|
23
|
-
|
|
24
|
-
const nonJoinedHeaderNames = [
|
|
25
|
-
'age',
|
|
26
|
-
'authorization',
|
|
27
|
-
'content-length',
|
|
28
|
-
'content-type',
|
|
29
|
-
'etag',
|
|
30
|
-
'expires',
|
|
31
|
-
'from',
|
|
32
|
-
'host',
|
|
33
|
-
'if-modified-since',
|
|
34
|
-
'if-unmodified-since',
|
|
35
|
-
'last-modified',
|
|
36
|
-
'location',
|
|
37
|
-
'max-forwards',
|
|
38
|
-
'proxy-authorization',
|
|
39
|
-
'referer',
|
|
40
|
-
'retry-after',
|
|
41
|
-
'server',
|
|
42
|
-
'user-agent',
|
|
43
|
-
]
|
|
44
|
-
|
|
45
|
-
describe('RequestHeaders', () => {
|
|
46
|
-
it('reads common headers without iterating rawHeaders', () => {
|
|
47
|
-
let rawHeadersReads = 0
|
|
48
|
-
const request = {
|
|
49
|
-
headers: { 'x-test': 'value' },
|
|
50
|
-
get rawHeaders() {
|
|
51
|
-
rawHeadersReads++
|
|
52
|
-
return ['x-test', 'value']
|
|
53
|
-
},
|
|
54
|
-
} as unknown as IncomingMessage
|
|
55
|
-
|
|
56
|
-
const headers = lightweightHeaders(request)
|
|
57
|
-
|
|
58
|
-
expect(headers).toBeInstanceOf(GlobalHeaders)
|
|
59
|
-
expect(headers.get('X-Test')).toBe('value')
|
|
60
|
-
expect(headers.has('x-test')).toBe(true)
|
|
61
|
-
expect(rawHeadersReads).toBe(0)
|
|
62
|
-
expect(() => headers.get('bad name')).toThrow(TypeError)
|
|
63
|
-
expect(() => headers.has(':path')).toThrow(TypeError)
|
|
64
|
-
expect(rawHeadersReads).toBe(0)
|
|
65
|
-
|
|
66
|
-
expect([...headers]).toEqual([['x-test', 'value']])
|
|
67
|
-
expect(rawHeadersReads).toBe(1)
|
|
68
|
-
})
|
|
69
|
-
|
|
70
|
-
it.each(nonJoinedHeaderNames)(
|
|
71
|
-
'combines repeated %s values consistently before and after iteration',
|
|
72
|
-
(name) => {
|
|
73
|
-
const rawHeaders = [name, 'one', name, 'two']
|
|
74
|
-
const collapsed = { [name]: 'one' }
|
|
75
|
-
|
|
76
|
-
const before = lightweightHeaders(incoming(rawHeaders, collapsed))
|
|
77
|
-
expect(before.get(name)).toBe('one, two')
|
|
78
|
-
expect(before.has(name)).toBe(true)
|
|
79
|
-
|
|
80
|
-
const after = lightweightHeaders(incoming(rawHeaders, collapsed))
|
|
81
|
-
void [...after]
|
|
82
|
-
expect(after.get(name)).toBe('one, two')
|
|
83
|
-
}
|
|
84
|
-
)
|
|
85
|
-
|
|
86
|
-
it('combines headers collapsed by the HTTP/2 parser', () => {
|
|
87
|
-
const headers = lightweightHeaders(
|
|
88
|
-
incomingHttp2(['if-none-match', '"a"', 'if-none-match', '"b"'], {
|
|
89
|
-
'if-none-match': '"a"',
|
|
90
|
-
})
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
expect(headers.get('if-none-match')).toBe('"a", "b"')
|
|
94
|
-
void [...headers]
|
|
95
|
-
expect(headers.get('if-none-match')).toBe('"a", "b"')
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
it('uses an immutable raw-header snapshot for HTTP/2', () => {
|
|
99
|
-
const rawHeaders = ['x-secret', 'topsecret', 'host', 'localhost']
|
|
100
|
-
const request = incomingHttp2(rawHeaders, {
|
|
101
|
-
'x-secret': 'topsecret',
|
|
102
|
-
host: 'localhost',
|
|
103
|
-
})
|
|
104
|
-
const headers = lightweightHeaders(request)
|
|
105
|
-
|
|
106
|
-
delete request.headers['x-secret']
|
|
107
|
-
request.headers['x-added'] = 'value'
|
|
108
|
-
rawHeaders[1] = 'changed'
|
|
109
|
-
rawHeaders.push('x-added', 'value')
|
|
110
|
-
|
|
111
|
-
expect(headers.get('x-secret')).toBe('topsecret')
|
|
112
|
-
expect(headers.has('x-added')).toBe(false)
|
|
113
|
-
void [...headers]
|
|
114
|
-
expect(headers.get('x-secret')).toBe('topsecret')
|
|
115
|
-
expect(headers.has('x-added')).toBe(false)
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
it('ignores non-string values in synthesized parsed headers', () => {
|
|
119
|
-
const headers = lightweightHeaders(
|
|
120
|
-
incoming(['content-length', '123'], { 'content-length': 123 })
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
expect(headers.get('content-length')).toBe('123')
|
|
124
|
-
expect(headers.has('content-length')).toBe(true)
|
|
125
|
-
void [...headers]
|
|
126
|
-
expect(headers.get('content-length')).toBe('123')
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
it('normalizes raw values consistently before and after materialization', () => {
|
|
130
|
-
const rawHeaders = ['x-token', ' abc\t', 'x-tab', '\tv v\t', 'x-interior', 'a b']
|
|
131
|
-
const headers = lightweightHeaders(incomingHttp2(rawHeaders, {}))
|
|
132
|
-
|
|
133
|
-
expect(headers.get('x-token')).toBe('abc')
|
|
134
|
-
expect(headers.get('x-tab')).toBe('v v')
|
|
135
|
-
expect(headers.get('x-interior')).toBe('a b')
|
|
136
|
-
void [...headers]
|
|
137
|
-
expect(headers.get('x-token')).toBe('abc')
|
|
138
|
-
expect(headers.get('x-tab')).toBe('v v')
|
|
139
|
-
expect(headers.get('x-interior')).toBe('a b')
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
it('fails closed on values rejected by native Headers', () => {
|
|
143
|
-
const rawHeaders = ['x-evil', 'ok', 'x-evil', 'bad\0value']
|
|
144
|
-
|
|
145
|
-
expect(() => lightweightHeaders(incomingHttp2(rawHeaders, {})).get('x-evil')).toThrow(TypeError)
|
|
146
|
-
expect(() => lightweightHeaders(incomingHttp2(rawHeaders, {})).has('x-evil')).toThrow(TypeError)
|
|
147
|
-
expect(() => [...lightweightHeaders(incomingHttp2(rawHeaders, {}))]).toThrow(TypeError)
|
|
148
|
-
})
|
|
149
|
-
|
|
150
|
-
it('preserves cookie and set-cookie representations', () => {
|
|
151
|
-
const headers = lightweightHeaders(
|
|
152
|
-
incoming(['cookie', 'a=1', 'cookie', 'b=2', 'set-cookie', 'a=1', 'set-cookie', 'b=2'], {
|
|
153
|
-
cookie: 'a=1; b=2',
|
|
154
|
-
'set-cookie': ['ignored'],
|
|
155
|
-
})
|
|
156
|
-
)
|
|
157
|
-
|
|
158
|
-
expect(headers.get('cookie')).toBe('a=1; b=2')
|
|
159
|
-
expect(headers.get('set-cookie')).toBe('a=1, b=2')
|
|
160
|
-
expect(headers.getSetCookie()).toEqual(['a=1', 'b=2'])
|
|
161
|
-
expect(Object.fromEntries(headers).cookie).toBe('a=1; b=2')
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
it('reads a literal __proto__ header without exposing prototype properties', () => {
|
|
165
|
-
const headers = lightweightHeaders(
|
|
166
|
-
incoming(['__proto__', 'value', 'x-test', 'one'], { 'x-test': 'one' })
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
expect(headers.get('__proto__')).toBe('value')
|
|
170
|
-
expect(headers.has('__proto__')).toBe(true)
|
|
171
|
-
expect(headers.get('toString')).toBe(null)
|
|
172
|
-
expect(headers.has('toString')).toBe(false)
|
|
173
|
-
})
|
|
174
|
-
|
|
175
|
-
it('materializes for validation and mutation while preserving identity', () => {
|
|
176
|
-
const headers = lightweightHeaders(incoming(['host', 'localhost'], { host: 'localhost' }))
|
|
177
|
-
|
|
178
|
-
expect(() => headers.get('bad name')).toThrow(TypeError)
|
|
179
|
-
expect(() => headers.has(':path')).toThrow(TypeError)
|
|
180
|
-
headers.set('x-test', 'value')
|
|
181
|
-
headers.append('x-test', 'second')
|
|
182
|
-
|
|
183
|
-
expect(headers.get('x-test')).toBe('value, second')
|
|
184
|
-
let callbackParent: GlobalHeaders | undefined
|
|
185
|
-
headers.forEach((_value, _key, parent) => {
|
|
186
|
-
callbackParent = parent
|
|
187
|
-
})
|
|
188
|
-
expect(callbackParent).toBe(headers)
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
it('uses the lightweight inspection format', () => {
|
|
192
|
-
const headers = lightweightHeaders(incoming(['x-test', 'value'], { 'x-test': 'value' }))
|
|
193
|
-
|
|
194
|
-
expect(inspect(headers)).toContain("Headers (lightweight) { 'x-test': 'value' }")
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
it('leaves the standard Headers constructor unchanged', () => {
|
|
198
|
-
const headers = new Headers({ 'x-test': 'one' })
|
|
199
|
-
headers.append('x-test', 'two')
|
|
200
|
-
|
|
201
|
-
expect(global.Headers).toBe(GlobalHeaders)
|
|
202
|
-
expect(Object.getPrototypeOf(headers)).toBe(GlobalHeaders.prototype)
|
|
203
|
-
expect(headers.get('x-test')).toBe('one, two')
|
|
204
|
-
expect(new Headers(headers).get('x-test')).toBe('one, two')
|
|
205
|
-
expect(new Headers({ rawHeaders: 'ordinary value' }).get('rawHeaders')).toBe('ordinary value')
|
|
206
|
-
})
|
|
207
|
-
|
|
208
|
-
it('uses the internal implementation without replacing the global constructor', () => {
|
|
209
|
-
const request = incoming(['x-test', 'value'], { 'x-test': 'value' })
|
|
210
|
-
const headers = newHeadersFromIncoming(request)
|
|
211
|
-
|
|
212
|
-
expect(global.Headers).toBe(GlobalHeaders)
|
|
213
|
-
expect(Object.getPrototypeOf(headers)).toBe(RequestHeaders.prototype)
|
|
214
|
-
expect(headers).toBeInstanceOf(GlobalHeaders)
|
|
215
|
-
expect(new GlobalHeaders(headers).get('x-test')).toBe('value')
|
|
216
|
-
})
|
|
217
|
-
|
|
218
|
-
it('uses the live global Headers constructor when it changes after module initialization', () => {
|
|
219
|
-
class PolyfillHeaders extends GlobalHeaders {}
|
|
220
|
-
const descriptor = Object.getOwnPropertyDescriptor(globalThis, 'Headers')
|
|
221
|
-
Object.defineProperty(globalThis, 'Headers', {
|
|
222
|
-
value: PolyfillHeaders,
|
|
223
|
-
configurable: true,
|
|
224
|
-
writable: true,
|
|
225
|
-
})
|
|
226
|
-
|
|
227
|
-
try {
|
|
228
|
-
const headers = newHeadersFromIncoming(incoming(['x-test', 'value'], { 'x-test': 'value' }))
|
|
229
|
-
|
|
230
|
-
expect(headers).toBeInstanceOf(PolyfillHeaders)
|
|
231
|
-
expect(Object.getPrototypeOf(headers)).toBe(PolyfillHeaders.prototype)
|
|
232
|
-
expect(headers.get('x-test')).toBe('value')
|
|
233
|
-
} finally {
|
|
234
|
-
Object.defineProperty(globalThis, 'Headers', descriptor!)
|
|
235
|
-
}
|
|
236
|
-
})
|
|
237
|
-
|
|
238
|
-
it('can initialize and clone a native Request after header mutation', () => {
|
|
239
|
-
const request = newRequest({
|
|
240
|
-
method: 'GET',
|
|
241
|
-
url: '/',
|
|
242
|
-
headers: { host: 'localhost' },
|
|
243
|
-
rawHeaders: ['host', 'localhost'],
|
|
244
|
-
} as IncomingMessage)
|
|
245
|
-
const headers = request.headers
|
|
246
|
-
headers.set('x-test', 'value')
|
|
247
|
-
|
|
248
|
-
expect(request.keepalive).toBe(false)
|
|
249
|
-
expect(request.headers).toBe(headers)
|
|
250
|
-
expect(new LightweightRequest(request).headers.get('x-test')).toBe('value')
|
|
251
|
-
})
|
|
252
|
-
})
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import { once } from 'node:events'
|
|
2
|
-
import { request as requestHTTP } from 'node:http'
|
|
3
|
-
import type { IncomingMessage, RequestOptions } from 'node:http'
|
|
4
|
-
import { connect } from 'node:http2'
|
|
5
|
-
import type { IncomingHttpHeaders as IncomingHttp2Headers } from 'node:http2'
|
|
6
|
-
import { Server as HttpsServer, request as requestHTTPS } from 'node:https'
|
|
7
|
-
import type { AddressInfo } from 'node:net'
|
|
8
|
-
import { newHeadersFromIncoming } from '../../../src/adapter/headers.ts'
|
|
9
|
-
import { GlobalResponse } from '../../../src/adapter/response.ts'
|
|
10
|
-
import type { ServerType } from '../../../src/adapter/types.ts'
|
|
11
|
-
|
|
12
|
-
export type ServerRequestInit = Omit<
|
|
13
|
-
RequestOptions,
|
|
14
|
-
'agent' | 'host' | 'hostname' | 'path' | 'port' | 'protocol'
|
|
15
|
-
> & {
|
|
16
|
-
body?: string | Uint8Array
|
|
17
|
-
path: string
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export type ServerRequestHooks = {
|
|
21
|
-
onHeaders?: (headers: Headers, status: number) => void
|
|
22
|
-
onChunk?: (chunk: Buffer, index: number) => void
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export type Http2RequestInit = {
|
|
26
|
-
headers?: Record<string, string>
|
|
27
|
-
method?: string
|
|
28
|
-
path: string
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const ensureListening = async (server: ServerType) => {
|
|
32
|
-
let address = server.address() as AddressInfo | null
|
|
33
|
-
let startedByHelper = false
|
|
34
|
-
if (!address) {
|
|
35
|
-
server.listen(0, '127.0.0.1')
|
|
36
|
-
await once(server, 'listening')
|
|
37
|
-
startedByHelper = true
|
|
38
|
-
address = server.address() as AddressInfo | null
|
|
39
|
-
}
|
|
40
|
-
if (!address) {
|
|
41
|
-
throw new Error('Server is not listening on a TCP address')
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
address,
|
|
46
|
-
// a no-op if the server was already listening before the request, its
|
|
47
|
-
// owner is responsible for closing it in that case
|
|
48
|
-
close: async () => {
|
|
49
|
-
if (startedByHelper) {
|
|
50
|
-
await new Promise<void>((resolve) => server.close(() => resolve()))
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const sendRequest = (server: ServerType, address: AddressInfo, init: ServerRequestInit) => {
|
|
57
|
-
const { body, path, ...options } = init
|
|
58
|
-
const common = {
|
|
59
|
-
...options,
|
|
60
|
-
agent: false,
|
|
61
|
-
hostname: address.address,
|
|
62
|
-
path,
|
|
63
|
-
port: address.port,
|
|
64
|
-
}
|
|
65
|
-
const request =
|
|
66
|
-
server instanceof HttpsServer
|
|
67
|
-
? requestHTTPS({ ...common, rejectUnauthorized: false })
|
|
68
|
-
: requestHTTP(common)
|
|
69
|
-
request.end(body)
|
|
70
|
-
return request
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const receiveResponse = async (request: ReturnType<typeof sendRequest>) => {
|
|
74
|
-
const [incoming] = (await once(request, 'response')) as [IncomingMessage]
|
|
75
|
-
const status = incoming.statusCode
|
|
76
|
-
if (!status) {
|
|
77
|
-
throw new Error('Server response did not include a status code')
|
|
78
|
-
}
|
|
79
|
-
return { incoming, status }
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export const requestServer = async (
|
|
83
|
-
server: ServerType,
|
|
84
|
-
init: ServerRequestInit
|
|
85
|
-
): Promise<Response> => {
|
|
86
|
-
const { address, close } = await ensureListening(server)
|
|
87
|
-
|
|
88
|
-
// the request may fail mid-flight (e.g. aborted via `init.signal`), so the
|
|
89
|
-
// helper-started server is always fully closed before returning or
|
|
90
|
-
// surfacing an error
|
|
91
|
-
try {
|
|
92
|
-
const { incoming, status } = await receiveResponse(sendRequest(server, address, init))
|
|
93
|
-
|
|
94
|
-
const hasBody = init.method?.toUpperCase() !== 'HEAD' && ![101, 204, 205, 304].includes(status)
|
|
95
|
-
|
|
96
|
-
let responseBody: BodyInit | null = null
|
|
97
|
-
if (hasBody) {
|
|
98
|
-
// buffer the body so a helper-started server can be fully closed before
|
|
99
|
-
// returning, otherwise a subsequent request could hit a half-closed server
|
|
100
|
-
const chunks: Buffer[] = []
|
|
101
|
-
for await (const chunk of incoming) {
|
|
102
|
-
chunks.push(chunk)
|
|
103
|
-
}
|
|
104
|
-
responseBody = new Uint8Array(Buffer.concat(chunks))
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return new GlobalResponse(responseBody, {
|
|
108
|
-
headers: newHeadersFromIncoming(incoming),
|
|
109
|
-
status,
|
|
110
|
-
statusText: incoming.statusMessage,
|
|
111
|
-
})
|
|
112
|
-
} finally {
|
|
113
|
-
await close()
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Same as `requestServer`, but exposes the raw body chunks for tests that
|
|
119
|
-
* assert streaming behavior: `onHeaders` fires before any body data arrives
|
|
120
|
-
* and `onChunk` fires per received chunk, so a test can synchronize with the
|
|
121
|
-
* server mid-response. Chunk boundaries are preserved by the chunked
|
|
122
|
-
* transfer-encoding framing.
|
|
123
|
-
*/
|
|
124
|
-
export const requestServerChunked = async (
|
|
125
|
-
server: ServerType,
|
|
126
|
-
init: ServerRequestInit,
|
|
127
|
-
hooks: ServerRequestHooks = {}
|
|
128
|
-
): Promise<{ chunks: Buffer[]; response: Response }> => {
|
|
129
|
-
const { address, close } = await ensureListening(server)
|
|
130
|
-
|
|
131
|
-
try {
|
|
132
|
-
const { incoming, status } = await receiveResponse(sendRequest(server, address, init))
|
|
133
|
-
const headers = newHeadersFromIncoming(incoming)
|
|
134
|
-
hooks.onHeaders?.(headers, status)
|
|
135
|
-
|
|
136
|
-
const chunks: Buffer[] = []
|
|
137
|
-
incoming.on('data', (chunk: Buffer) => {
|
|
138
|
-
hooks.onChunk?.(chunk, chunks.length)
|
|
139
|
-
chunks.push(chunk)
|
|
140
|
-
})
|
|
141
|
-
await once(incoming, 'end')
|
|
142
|
-
|
|
143
|
-
return {
|
|
144
|
-
chunks,
|
|
145
|
-
response: new GlobalResponse(new Uint8Array(Buffer.concat(chunks)), {
|
|
146
|
-
headers,
|
|
147
|
-
status,
|
|
148
|
-
statusText: incoming.statusMessage,
|
|
149
|
-
}),
|
|
150
|
-
}
|
|
151
|
-
} finally {
|
|
152
|
-
await close()
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
export const requestServerHttp2 = async (
|
|
157
|
-
server: ServerType,
|
|
158
|
-
init: Http2RequestInit
|
|
159
|
-
): Promise<Response> => {
|
|
160
|
-
const { address, close } = await ensureListening(server)
|
|
161
|
-
const client = connect(`http://${address.address}:${address.port}`)
|
|
162
|
-
// stream errors reject `once()` below, a session error would otherwise crash
|
|
163
|
-
client.once('error', () => {})
|
|
164
|
-
|
|
165
|
-
try {
|
|
166
|
-
const stream = client.request({
|
|
167
|
-
':method': init.method ?? 'GET',
|
|
168
|
-
':path': init.path,
|
|
169
|
-
...init.headers,
|
|
170
|
-
})
|
|
171
|
-
stream.end()
|
|
172
|
-
|
|
173
|
-
const [incomingHeaders, , rawHeaders] = (await once(stream, 'response')) as [
|
|
174
|
-
IncomingHttp2Headers,
|
|
175
|
-
number,
|
|
176
|
-
string[],
|
|
177
|
-
]
|
|
178
|
-
const status = Number(incomingHeaders[':status'])
|
|
179
|
-
const headers = newHeadersFromIncoming({ rawHeaders })
|
|
180
|
-
|
|
181
|
-
const chunks: Buffer[] = []
|
|
182
|
-
stream.on('data', (chunk: Buffer) => chunks.push(chunk))
|
|
183
|
-
await once(stream, 'end')
|
|
184
|
-
|
|
185
|
-
return new GlobalResponse(new Uint8Array(Buffer.concat(chunks)), { headers, status })
|
|
186
|
-
} finally {
|
|
187
|
-
client.close()
|
|
188
|
-
await close()
|
|
189
|
-
}
|
|
190
|
-
}
|