@johntalton/http-core 1.0.3 → 1.0.5
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/package.json +2 -2
- package/src/epilogue.js +2 -2
- package/src/index.js +11 -0
- package/src/preamble.js +23 -8
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@johntalton/http-core",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.5",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./src/index.js"
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"scripts": {
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@johntalton/http-util": "^
|
|
18
|
+
"@johntalton/http-util": "^6.0.0",
|
|
19
19
|
"@johntalton/sse-util": "^1.0.0"
|
|
20
20
|
}
|
|
21
21
|
}
|
package/src/epilogue.js
CHANGED
|
@@ -24,7 +24,7 @@ function addSSEPortHandler(stream, port, streamId, shutdownSignal) {
|
|
|
24
24
|
port.close()
|
|
25
25
|
}))
|
|
26
26
|
|
|
27
|
-
shutdownSignal.addEventListener('abort', signalHandler)
|
|
27
|
+
shutdownSignal.addEventListener('abort', signalHandler, { once: true })
|
|
28
28
|
|
|
29
29
|
// ServerSentEvents.messageToEventStreamLines({
|
|
30
30
|
// comment: 'Welcome',
|
|
@@ -47,7 +47,7 @@ function addSSEPortHandler(stream, port, streamId, shutdownSignal) {
|
|
|
47
47
|
export function epilogue(state) {
|
|
48
48
|
const { type, stream, meta, streamId } = state
|
|
49
49
|
|
|
50
|
-
meta.customHeaders
|
|
50
|
+
meta.customHeaders?.push([ 'X-Request-Id', streamId ])
|
|
51
51
|
|
|
52
52
|
switch(type) {
|
|
53
53
|
//
|
package/src/index.js
CHANGED
|
@@ -44,6 +44,8 @@ export const KNOWN_METHODS = [
|
|
|
44
44
|
/** @import { BodyFuture } from '@johntalton/http-util/body' */
|
|
45
45
|
/** @import { EtagItem, IMFFixDate, ContentRangeDirective, RateLimitPolicyInfo, RateLimitInfo, ChallengeItem } from '@johntalton/http-util/headers' */
|
|
46
46
|
/** @import { SendBody } from '@johntalton/http-util/response' */
|
|
47
|
+
/** @import { SecFetchSite, SecFetchMode, SecFetchDest } from '@johntalton/http-util/headers' */
|
|
48
|
+
|
|
47
49
|
|
|
48
50
|
/** @typedef {(state: RouteRequest|RouteAction) => Promise<RouteAction>} Router */
|
|
49
51
|
|
|
@@ -110,6 +112,7 @@ export const KNOWN_METHODS = [
|
|
|
110
112
|
* @property {RouteRequestAccept} accept
|
|
111
113
|
* @property {RouteRemoteClient} client
|
|
112
114
|
* @property {RouteConditions} conditions
|
|
115
|
+
* @property {SecFetchMetadata} secFetchMetadata
|
|
113
116
|
* @property {string} SNI
|
|
114
117
|
*/
|
|
115
118
|
/** @typedef {RouteBase & RouteRequestBase} RouteRequest */
|
|
@@ -165,6 +168,14 @@ export const KNOWN_METHODS = [
|
|
|
165
168
|
* @property {IMFFixDate|EtagItem|undefined} [range]
|
|
166
169
|
*/
|
|
167
170
|
|
|
171
|
+
/**
|
|
172
|
+
* @typedef {Object} SecFetchMetadata
|
|
173
|
+
* @property {SecFetchSite|undefined} site
|
|
174
|
+
* @property {SecFetchMode|undefined} mode
|
|
175
|
+
* @property {SecFetchDest|undefined} dest
|
|
176
|
+
*/
|
|
177
|
+
|
|
178
|
+
|
|
168
179
|
/**
|
|
169
180
|
* @typedef {Object} RoutePreflightBase
|
|
170
181
|
* @property {'preflight'} type
|
package/src/preamble.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** biome-ignore-all lint/nursery/noExcessiveLinesPerFile: does all the work */
|
|
1
2
|
import http2 from 'node:http2'
|
|
2
3
|
import { TLSSocket } from 'node:tls'
|
|
3
4
|
|
|
@@ -8,6 +9,7 @@ import {
|
|
|
8
9
|
AcceptLanguage,
|
|
9
10
|
|
|
10
11
|
Conditional,
|
|
12
|
+
ContentType,
|
|
11
13
|
ETag,
|
|
12
14
|
|
|
13
15
|
FORWARDED_KEY_FOR,
|
|
@@ -19,18 +21,21 @@ import {
|
|
|
19
21
|
MIME_TYPE_MESSAGE_HTTP,
|
|
20
22
|
MIME_TYPE_TEXT,
|
|
21
23
|
MIME_TYPE_XML,
|
|
22
|
-
|
|
24
|
+
SecFetch
|
|
23
25
|
} from '@johntalton/http-util/headers'
|
|
24
26
|
import {
|
|
25
27
|
ENCODER_MAP,
|
|
26
28
|
HTTP_HEADER_FORWARDED,
|
|
27
|
-
HTTP_HEADER_ORIGIN
|
|
29
|
+
HTTP_HEADER_ORIGIN,
|
|
30
|
+
HTTP_HEADER_SEC_FETCH_DEST,
|
|
31
|
+
HTTP_HEADER_SEC_FETCH_MODE,
|
|
32
|
+
HTTP_HEADER_SEC_FETCH_SITE
|
|
28
33
|
} from '@johntalton/http-util/response'
|
|
29
34
|
|
|
30
35
|
import { isValidHeader, isValidLikeHeader, isValidMethod } from './index.js'
|
|
31
36
|
|
|
32
37
|
/** @import { ServerHttp2Stream, IncomingHttpHeaders } from 'node:http2' */
|
|
33
|
-
/** @import { Config, RouteRequest, RouteAction, StreamID, RouteConditions } from './index.js' */
|
|
38
|
+
/** @import { Config, RouteRequest, RouteAction, StreamID, RouteConditions, SecFetchMetadata } from './index.js' */
|
|
34
39
|
|
|
35
40
|
const { HTTP2_METHOD_OPTIONS, HTTP2_METHOD_TRACE } = http2.constants
|
|
36
41
|
|
|
@@ -142,9 +147,9 @@ export function preamble(config, streamId, stream, headers, servername, shutdown
|
|
|
142
147
|
// const secUA = header[HTTP_HEADER_SEC_CH_UA]
|
|
143
148
|
// const secPlatform = header[HTTP_HEADER_SEC_CH_PLATFORM]
|
|
144
149
|
// const secMobile = header[HTTP_HEADER_SEC_CH_MOBILE]
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
150
|
+
const secFetchSite = headers[HTTP_HEADER_SEC_FETCH_SITE]
|
|
151
|
+
const secFetchMode = headers[HTTP_HEADER_SEC_FETCH_MODE]
|
|
152
|
+
const secFetchDest = headers[HTTP_HEADER_SEC_FETCH_DEST]
|
|
148
153
|
|
|
149
154
|
//
|
|
150
155
|
const allowedOrigin = (ALLOWED_ORIGINS.includes('*') || ((origin !== undefined) && URL.canParse(origin) && ALLOWED_ORIGINS.includes(origin))) ? origin : undefined
|
|
@@ -200,6 +205,15 @@ export function preamble(config, streamId, stream, headers, servername, shutdown
|
|
|
200
205
|
//
|
|
201
206
|
const requestUrl = new URL(fullPathAndQuery, `${scheme}://${authority}`)
|
|
202
207
|
|
|
208
|
+
// Sec Fetch Metadata
|
|
209
|
+
/** @type {SecFetchMetadata} */
|
|
210
|
+
const secFetchMetadata = {
|
|
211
|
+
site: SecFetch.parseSite(secFetchSite),
|
|
212
|
+
mode: SecFetch.parseMode(secFetchMode),
|
|
213
|
+
dest: SecFetch.parseDestination(secFetchDest)
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
|
|
203
217
|
//
|
|
204
218
|
/** @type {RouteConditions} */
|
|
205
219
|
const conditions = {
|
|
@@ -240,7 +254,7 @@ export function preamble(config, streamId, stream, headers, servername, shutdown
|
|
|
240
254
|
//
|
|
241
255
|
// content negotiation
|
|
242
256
|
//
|
|
243
|
-
const contentType =
|
|
257
|
+
const contentType = ContentType.parse(fullContentType)
|
|
244
258
|
const acceptedEncoding = AcceptEncoding.select(fullAcceptEncoding, DEFAULT_SUPPORTED_ENCODINGS)
|
|
245
259
|
const accept = Accept.select(fullAccept, DEFAULT_SUPPORTED_MIME_TYPES)
|
|
246
260
|
const acceptedLanguage = AcceptLanguage.select(fullAcceptLanguage, DEFAULT_SUPPORTED_LANGUAGES)
|
|
@@ -255,7 +269,7 @@ export function preamble(config, streamId, stream, headers, servername, shutdown
|
|
|
255
269
|
//
|
|
256
270
|
if(method === HTTP2_METHOD_TRACE) {
|
|
257
271
|
if(!ALLOW_TRACE) { return { ...state, type: 'not-allowed', method, methods: [], url: requestUrl }}
|
|
258
|
-
const maxForwardsValue = maxForwards
|
|
272
|
+
const maxForwardsValue = maxForwards === undefined ? 0 : Number.parseInt(maxForwards)
|
|
259
273
|
const preambleEnd = performance.now()
|
|
260
274
|
state.meta.performance.push({ name: 'preamble-trace', duration: preambleEnd - preambleStart })
|
|
261
275
|
if(acceptObject.type !== MIME_TYPE_MESSAGE_HTTP) { return { ...state, type: 'not-acceptable', acceptableMediaTypes: [ MIME_TYPE_MESSAGE_HTTP ] } }
|
|
@@ -294,6 +308,7 @@ export function preamble(config, streamId, stream, headers, servername, shutdown
|
|
|
294
308
|
body,
|
|
295
309
|
// tokens,
|
|
296
310
|
conditions,
|
|
311
|
+
secFetchMetadata,
|
|
297
312
|
accept: acceptObject,
|
|
298
313
|
client: { family, ip, port },
|
|
299
314
|
SNI
|