@johntalton/http-util 6.0.0 → 7.0.1
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 +1 -1
- package/package.json +17 -2
- package/src/defs.js +34 -1
- package/src/headers/accept-encoding.js +9 -12
- package/src/headers/accept-language.js +10 -4
- package/src/headers/accept.js +0 -28
- package/src/headers/cache-control.js +0 -6
- package/src/headers/clear-site-data.js +4 -10
- package/src/headers/client-hints.js +9 -2
- package/src/headers/conditional.js +170 -106
- package/src/headers/content-disposition.js +0 -14
- package/src/headers/content-range.js +0 -17
- package/src/headers/content-type.js +1 -1
- package/src/headers/forwarded.js +2 -33
- package/src/headers/link.js +11 -12
- package/src/headers/multipart.js +19 -18
- package/src/headers/preference.js +0 -43
- package/src/headers/range.js +5 -31
- package/src/headers/rate-limit.js +7 -2
- package/src/headers/server-timing.js +1 -14
- package/src/headers/strict-transport-security.js +1 -0
- package/src/headers/util/mime.js +3 -3
- package/src/headers/util/whitespace.js +3 -1
- package/src/headers/www-authenticate.js +0 -1
- package/src/response/2xx/bytes.js +19 -13
- package/src/response/2xx/created.js +16 -8
- package/src/response/2xx/json.js +29 -10
- package/src/response/2xx/no-content.js +12 -6
- package/src/response/2xx/partial-content.js +17 -14
- package/src/response/2xx/preflight.js +22 -10
- package/src/response/3xx/found.js +25 -0
- package/src/response/3xx/moved-permanently.js +7 -5
- package/src/response/3xx/not-modified.js +13 -8
- package/src/response/3xx/permanent-redirect.js +4 -2
- package/src/response/3xx/see-other.js +7 -5
- package/src/response/3xx/temporary-redirect.js +4 -2
- package/src/response/4xx/bad-request.js +19 -0
- package/src/response/4xx/content-too-large.js +1 -1
- package/src/response/4xx/gone.js +1 -1
- package/src/response/4xx/im-a-teapot.js +1 -1
- package/src/response/4xx/not-acceptable.js +6 -4
- package/src/response/4xx/not-allowed.js +6 -4
- package/src/response/4xx/payment-required.js +17 -0
- package/src/response/4xx/precondition-failed.js +18 -3
- package/src/response/4xx/range-not-satisfiable.js +5 -3
- package/src/response/4xx/too-many-requests.js +8 -5
- package/src/response/4xx/unauthorized.js +1 -1
- package/src/response/4xx/unsupported-media.js +9 -5
- package/src/response/5xx/error.js +2 -3
- package/src/response/5xx/insufficient-storage.js +2 -2
- package/src/response/5xx/not-implemented.js +2 -3
- package/src/response/5xx/unavailable.js +7 -12
- package/src/response/header-util.js +1 -1
- package/src/response/index.js +4 -0
- package/src/response/response.js +8 -2
- package/src/response/send-util.js +46 -14
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import http2 from 'node:http2'
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
|
+
HTTP_HEADER_ACCEPT_PATCH,
|
|
5
|
+
HTTP_HEADER_ACCEPT_POST,
|
|
4
6
|
HTTP_HEADER_ACCEPT_QUERY,
|
|
5
7
|
HTTP_METHOD_QUERY,
|
|
6
8
|
HTTP2_HEADER_ACCESS_CONTROL_MAX_AGE,
|
|
7
9
|
PREFLIGHT_AGE_SECONDS
|
|
10
|
+
|
|
8
11
|
} from '../../defs.js'
|
|
9
12
|
import { send } from '../send-util.js'
|
|
10
13
|
|
|
11
14
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
12
|
-
/** @import { Metadata } from '../../defs.js' */
|
|
15
|
+
/** @import { SendInfo, Metadata } from '../../defs.js' */
|
|
13
16
|
|
|
14
17
|
const {
|
|
15
18
|
HTTP2_HEADER_CONTENT_TYPE,
|
|
@@ -27,29 +30,38 @@ const { HTTP_STATUS_OK } = http2.constants
|
|
|
27
30
|
|
|
28
31
|
/**
|
|
29
32
|
* @param {ServerHttp2Stream} stream
|
|
30
|
-
* @param {
|
|
31
|
-
* @param {Array<string>|undefined} supportedQueryTypes
|
|
32
|
-
* @param {'byte'|'none'|undefined} acceptRanges
|
|
33
|
+
* @param {Pick<SendInfo, 'supportedMethods' | 'supportedQueryTypes' | 'acceptRanges'>} info
|
|
33
34
|
* @param {Metadata} meta
|
|
34
35
|
*/
|
|
35
|
-
export function sendPreflight(stream,
|
|
36
|
-
const
|
|
36
|
+
export function sendPreflight(stream, info, meta) {
|
|
37
|
+
const {
|
|
38
|
+
supportedMethods,
|
|
39
|
+
supportedQueryTypes,
|
|
40
|
+
acceptRanges
|
|
41
|
+
} = info
|
|
42
|
+
|
|
43
|
+
const supportsQuery = supportedMethods.includes(HTTP_METHOD_QUERY) && supportedQueryTypes !== undefined && supportedQueryTypes.length > 0
|
|
37
44
|
const exposedHeadersAcceptQuery = supportsQuery ? [ HTTP_HEADER_ACCEPT_QUERY ] : []
|
|
38
45
|
const exposedHeaders = acceptRanges === undefined ? exposedHeadersAcceptQuery : [ HTTP2_HEADER_ACCEPT_RANGES, ...exposedHeadersAcceptQuery ]
|
|
39
46
|
|
|
47
|
+
// todo: if supportedMethods includes POST | PATCH
|
|
48
|
+
// include accept-post / accept-patch headers
|
|
49
|
+
|
|
40
50
|
send(stream, HTTP_STATUS_OK, {
|
|
41
|
-
[HTTP2_HEADER_ACCESS_CONTROL_ALLOW_METHODS]:
|
|
51
|
+
[HTTP2_HEADER_ACCESS_CONTROL_ALLOW_METHODS]: supportedMethods.join(','),
|
|
42
52
|
[HTTP2_HEADER_ACCESS_CONTROL_ALLOW_HEADERS]: [
|
|
43
53
|
HTTP2_HEADER_IF_MATCH,
|
|
44
54
|
HTTP2_HEADER_IF_NONE_MATCH,
|
|
45
55
|
HTTP2_HEADER_AUTHORIZATION,
|
|
46
|
-
HTTP2_HEADER_CONTENT_TYPE,
|
|
47
|
-
HTTP2_HEADER_RANGE,
|
|
56
|
+
HTTP2_HEADER_CONTENT_TYPE, // overrides cors safe restriction (for json)
|
|
57
|
+
HTTP2_HEADER_RANGE, // todo cors safe override not needed
|
|
48
58
|
HTTP2_HEADER_IF_RANGE
|
|
49
59
|
].join(','),
|
|
50
60
|
[HTTP2_HEADER_ACCESS_CONTROL_MAX_AGE]: PREFLIGHT_AGE_SECONDS,
|
|
61
|
+
// [HTTP_HEADER_ACCEPT_POST]: ,
|
|
62
|
+
// [HTTP_HEADER_ACCEPT_PATCH]: ,
|
|
51
63
|
[HTTP2_HEADER_ACCEPT_RANGES]: acceptRanges,
|
|
52
|
-
[HTTP_HEADER_ACCEPT_QUERY]: supportedQueryTypes?.join(',')
|
|
64
|
+
[HTTP_HEADER_ACCEPT_QUERY]: supportedQueryTypes?.join(',') // todo should empty array return undef
|
|
53
65
|
// Access-Control-Allow-Credentials
|
|
54
66
|
}, exposedHeaders, undefined, undefined, meta)
|
|
55
67
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import http2 from 'node:http2'
|
|
2
|
+
|
|
3
|
+
import { send } from '../send-util.js'
|
|
4
|
+
|
|
5
|
+
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
6
|
+
/** @import { Metadata } from '../../defs.js' */
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
HTTP2_HEADER_LOCATION
|
|
10
|
+
} = http2.constants
|
|
11
|
+
|
|
12
|
+
const { HTTP_STATUS_FOUND } = http2.constants
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @param {ServerHttp2Stream} stream
|
|
16
|
+
* @param {URL|string} location
|
|
17
|
+
* @param {Metadata} meta
|
|
18
|
+
*/
|
|
19
|
+
export function sendFound(stream, location, meta) {
|
|
20
|
+
const loc = (location instanceof URL) ? location.href : location
|
|
21
|
+
|
|
22
|
+
send(stream, HTTP_STATUS_FOUND, {
|
|
23
|
+
[HTTP2_HEADER_LOCATION]: loc
|
|
24
|
+
}, [ HTTP2_HEADER_LOCATION ], undefined, undefined, meta)
|
|
25
|
+
}
|
|
@@ -6,18 +6,20 @@ import { send } from '../send-util.js'
|
|
|
6
6
|
/** @import { Metadata } from '../../defs.js' */
|
|
7
7
|
|
|
8
8
|
const {
|
|
9
|
-
|
|
9
|
+
HTTP2_HEADER_LOCATION
|
|
10
10
|
} = http2.constants
|
|
11
11
|
|
|
12
12
|
const { HTTP_STATUS_MOVED_PERMANENTLY } = http2.constants
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* @param {ServerHttp2Stream} stream
|
|
16
|
-
* @param {URL} location
|
|
16
|
+
* @param {URL|string} location
|
|
17
17
|
* @param {Metadata} meta
|
|
18
18
|
*/
|
|
19
19
|
export function sendMovedPermanently(stream, location, meta) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
const loc = (location instanceof URL) ? location.href : location
|
|
21
|
+
|
|
22
|
+
send(stream, HTTP_STATUS_MOVED_PERMANENTLY, {
|
|
23
|
+
[HTTP2_HEADER_LOCATION]: loc
|
|
24
|
+
}, [HTTP2_HEADER_LOCATION], undefined, undefined, meta)
|
|
23
25
|
}
|
|
@@ -5,13 +5,12 @@ import { Conditional } from '../../headers/conditional.js'
|
|
|
5
5
|
import { send } from '../send-util.js'
|
|
6
6
|
|
|
7
7
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
8
|
-
/** @import { Metadata } from '../../defs.js' */
|
|
9
|
-
/** @import { EtagItem } from '../../headers/conditional.js' */
|
|
10
|
-
/** @import { CacheControlOptions } from '../../headers/cache-control.js' */
|
|
8
|
+
/** @import { SendContent, Metadata } from '../../defs.js' */
|
|
11
9
|
|
|
12
10
|
const {
|
|
13
11
|
HTTP2_HEADER_AGE,
|
|
14
12
|
HTTP2_HEADER_ETAG,
|
|
13
|
+
HTTP2_HEADER_LAST_MODIFIED,
|
|
15
14
|
HTTP2_HEADER_VARY,
|
|
16
15
|
HTTP2_HEADER_CACHE_CONTROL
|
|
17
16
|
} = http2.constants
|
|
@@ -20,16 +19,22 @@ const { HTTP_STATUS_NOT_MODIFIED } = http2.constants
|
|
|
20
19
|
|
|
21
20
|
/**
|
|
22
21
|
* @param {ServerHttp2Stream} stream
|
|
23
|
-
* @param {
|
|
24
|
-
* @param {number|undefined} age
|
|
25
|
-
* @param {CacheControlOptions} cacheControl
|
|
22
|
+
* @param {Pick<SendContent, 'etag' | 'lastModified' | 'age' | 'cacheControl'>} content
|
|
26
23
|
* @param {Metadata} meta
|
|
27
24
|
*/
|
|
28
|
-
export function sendNotModified(stream,
|
|
25
|
+
export function sendNotModified(stream, content, meta) {
|
|
26
|
+
const {
|
|
27
|
+
etag,
|
|
28
|
+
lastModified,
|
|
29
|
+
age,
|
|
30
|
+
cacheControl
|
|
31
|
+
} = content
|
|
32
|
+
|
|
29
33
|
send(stream, HTTP_STATUS_NOT_MODIFIED, {
|
|
30
34
|
[HTTP2_HEADER_VARY]: 'Accept, Accept-Encoding',
|
|
31
35
|
[HTTP2_HEADER_CACHE_CONTROL]: CacheControl.encode(cacheControl),
|
|
32
36
|
[HTTP2_HEADER_ETAG]: Conditional.encodeEtag(etag),
|
|
33
|
-
[
|
|
37
|
+
[HTTP2_HEADER_LAST_MODIFIED]: Conditional.encodeFixDate(lastModified),
|
|
38
|
+
[HTTP2_HEADER_AGE]: Number.isInteger(age) ? `${age}` : undefined
|
|
34
39
|
}, [ HTTP2_HEADER_AGE ], undefined, undefined, meta)
|
|
35
40
|
}
|
|
@@ -13,11 +13,13 @@ const { HTTP_STATUS_PERMANENT_REDIRECT } = http2.constants
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* @param {ServerHttp2Stream} stream
|
|
16
|
-
* @param {URL} location
|
|
16
|
+
* @param {URL|string} location
|
|
17
17
|
* @param {Metadata} meta
|
|
18
18
|
*/
|
|
19
19
|
export function sendPermanentRedirect(stream, location, meta) {
|
|
20
|
+
const loc = (location instanceof URL) ? location.href : location
|
|
21
|
+
|
|
20
22
|
send(stream, HTTP_STATUS_PERMANENT_REDIRECT, {
|
|
21
|
-
[HTTP2_HEADER_LOCATION]:
|
|
23
|
+
[HTTP2_HEADER_LOCATION]: loc
|
|
22
24
|
}, [ HTTP2_HEADER_LOCATION ], undefined, undefined, meta)
|
|
23
25
|
}
|
|
@@ -6,18 +6,20 @@ import { send } from '../send-util.js'
|
|
|
6
6
|
/** @import { Metadata } from '../../defs.js' */
|
|
7
7
|
|
|
8
8
|
const {
|
|
9
|
-
|
|
9
|
+
HTTP2_HEADER_LOCATION
|
|
10
10
|
} = http2.constants
|
|
11
11
|
|
|
12
12
|
const { HTTP_STATUS_SEE_OTHER } = http2.constants
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* @param {ServerHttp2Stream} stream
|
|
16
|
-
* @param {URL} location
|
|
16
|
+
* @param {URL|string} location
|
|
17
17
|
* @param {Metadata} meta
|
|
18
18
|
*/
|
|
19
19
|
export function sendSeeOther(stream, location, meta) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
const loc = (location instanceof URL) ? location.href : location
|
|
21
|
+
|
|
22
|
+
send(stream, HTTP_STATUS_SEE_OTHER, {
|
|
23
|
+
[HTTP2_HEADER_LOCATION]: loc
|
|
24
|
+
}, [HTTP2_HEADER_LOCATION], undefined, undefined, meta)
|
|
23
25
|
}
|
|
@@ -13,11 +13,13 @@ const { HTTP_STATUS_TEMPORARY_REDIRECT } = http2.constants
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* @param {ServerHttp2Stream} stream
|
|
16
|
-
* @param {URL} location
|
|
16
|
+
* @param {URL|string} location
|
|
17
17
|
* @param {Metadata} meta
|
|
18
18
|
*/
|
|
19
19
|
export function sendTemporaryRedirect(stream, location, meta) {
|
|
20
|
+
const loc = (location instanceof URL) ? location.href : location
|
|
21
|
+
|
|
20
22
|
send(stream, HTTP_STATUS_TEMPORARY_REDIRECT, {
|
|
21
|
-
[HTTP2_HEADER_LOCATION]:
|
|
23
|
+
[HTTP2_HEADER_LOCATION]: loc
|
|
22
24
|
}, [ HTTP2_HEADER_LOCATION ], undefined, undefined, meta)
|
|
23
25
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import http2 from 'node:http2'
|
|
2
|
+
|
|
3
|
+
import { CONTENT_TYPE_TEXT } from '../../headers/content-type.js'
|
|
4
|
+
import { send } from '../send-util.js'
|
|
5
|
+
|
|
6
|
+
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
7
|
+
/** @import { Metadata } from '../../defs.js' */
|
|
8
|
+
|
|
9
|
+
const { HTTP_STATUS_BAD_REQUEST } = http2.constants
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {ServerHttp2Stream} stream
|
|
13
|
+
* @param {string} message
|
|
14
|
+
* @param {Metadata} meta
|
|
15
|
+
*/
|
|
16
|
+
export function sendBadRequest(stream, message, meta) {
|
|
17
|
+
send(stream, HTTP_STATUS_BAD_REQUEST, {
|
|
18
|
+
}, [], CONTENT_TYPE_TEXT, message, meta)
|
|
19
|
+
}
|
|
@@ -12,5 +12,5 @@ const { HTTP_STATUS_PAYLOAD_TOO_LARGE } = http2.constants
|
|
|
12
12
|
* @param {Metadata} meta
|
|
13
13
|
*/
|
|
14
14
|
export function sendContentTooLarge(stream, meta) {
|
|
15
|
-
|
|
15
|
+
send(stream, HTTP_STATUS_PAYLOAD_TOO_LARGE, {}, [], undefined, undefined, meta)
|
|
16
16
|
}
|
package/src/response/4xx/gone.js
CHANGED
|
@@ -12,5 +12,5 @@ const { HTTP_STATUS_GONE } = http2.constants
|
|
|
12
12
|
* @param {Metadata} meta
|
|
13
13
|
*/
|
|
14
14
|
export function sendGone(stream, meta) {
|
|
15
|
-
|
|
15
|
+
send(stream, HTTP_STATUS_GONE, {}, [], undefined, undefined, meta)
|
|
16
16
|
}
|
|
@@ -12,5 +12,5 @@ const { HTTP_STATUS_TEAPOT } = http2.constants
|
|
|
12
12
|
* @param {Metadata} meta
|
|
13
13
|
*/
|
|
14
14
|
export function sendImATeapot(stream, meta) {
|
|
15
|
-
|
|
15
|
+
send(stream, HTTP_STATUS_TEAPOT, {}, [], undefined, undefined, meta)
|
|
16
16
|
}
|
|
@@ -4,16 +4,18 @@ import { CONTENT_TYPE_JSON } from '../../headers/content-type.js'
|
|
|
4
4
|
import { send } from '../send-util.js'
|
|
5
5
|
|
|
6
6
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
7
|
-
/** @import { Metadata } from '../../defs.js' */
|
|
7
|
+
/** @import { SendInfo, Metadata } from '../../defs.js' */
|
|
8
8
|
|
|
9
9
|
const { HTTP_STATUS_NOT_ACCEPTABLE } = http2.constants
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* @param {ServerHttp2Stream} stream
|
|
13
|
-
* @param {
|
|
13
|
+
* @param {Pick<SendInfo, 'supportedTypes'>} info
|
|
14
14
|
* @param {Metadata} meta
|
|
15
15
|
*/
|
|
16
|
-
export function sendNotAcceptable(stream,
|
|
16
|
+
export function sendNotAcceptable(stream, info, meta) {
|
|
17
|
+
const { supportedTypes } = info
|
|
18
|
+
|
|
17
19
|
const supportedTypesList = Array.isArray(supportedTypes) ? supportedTypes : [ supportedTypes ]
|
|
18
20
|
const has = supportedTypesList.length > 0
|
|
19
21
|
|
|
@@ -22,6 +24,6 @@ export function sendNotAcceptable(stream, supportedTypes, meta) {
|
|
|
22
24
|
{},
|
|
23
25
|
[],
|
|
24
26
|
has ? CONTENT_TYPE_JSON : undefined,
|
|
25
|
-
has ? JSON.stringify(supportedTypes) : undefined,
|
|
27
|
+
has ? JSON.stringify({ supportedTypes: supportedTypesList }) : undefined,
|
|
26
28
|
meta)
|
|
27
29
|
}
|
|
@@ -3,7 +3,7 @@ import http2 from 'node:http2'
|
|
|
3
3
|
import { send } from '../send-util.js'
|
|
4
4
|
|
|
5
5
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
6
|
-
/** @import { Metadata } from '../../defs.js' */
|
|
6
|
+
/** @import { SendInfo, Metadata } from '../../defs.js' */
|
|
7
7
|
|
|
8
8
|
const {
|
|
9
9
|
HTTP_STATUS_METHOD_NOT_ALLOWED
|
|
@@ -13,11 +13,13 @@ const { HTTP2_HEADER_ALLOW } = http2.constants
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* @param {ServerHttp2Stream} stream
|
|
16
|
-
* @param {
|
|
16
|
+
* @param {Pick<SendInfo, 'supportedMethods'>} info
|
|
17
17
|
* @param {Metadata} meta
|
|
18
18
|
*/
|
|
19
|
-
export function sendNotAllowed(stream,
|
|
19
|
+
export function sendNotAllowed(stream, info, meta) {
|
|
20
|
+
const { supportedMethods } = info
|
|
21
|
+
|
|
20
22
|
send(stream, HTTP_STATUS_METHOD_NOT_ALLOWED, {
|
|
21
|
-
[HTTP2_HEADER_ALLOW]:
|
|
23
|
+
[HTTP2_HEADER_ALLOW]: supportedMethods.join(',')
|
|
22
24
|
}, [ HTTP2_HEADER_ALLOW ], undefined, undefined, meta)
|
|
23
25
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import http2 from 'node:http2'
|
|
2
|
+
|
|
3
|
+
import { send } from '../send-util.js'
|
|
4
|
+
|
|
5
|
+
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
6
|
+
/** @import { Metadata } from '../../defs.js' */
|
|
7
|
+
|
|
8
|
+
const { HTTP_STATUS_PAYMENT_REQUIRED } = http2.constants
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {ServerHttp2Stream} stream
|
|
12
|
+
* @param {Metadata} meta
|
|
13
|
+
*/
|
|
14
|
+
export function sendPaymentRequired(stream, meta) {
|
|
15
|
+
send(stream, HTTP_STATUS_PAYMENT_REQUIRED, {
|
|
16
|
+
}, [ ], undefined, undefined, meta)
|
|
17
|
+
}
|
|
@@ -1,16 +1,31 @@
|
|
|
1
1
|
import http2 from 'node:http2'
|
|
2
2
|
|
|
3
|
+
import { Conditional } from '../../headers/conditional.js'
|
|
3
4
|
import { send } from '../send-util.js'
|
|
4
5
|
|
|
5
6
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
6
|
-
/** @import { Metadata } from '../../defs.js' */
|
|
7
|
+
/** @import { SendContent, Metadata } from '../../defs.js' */
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
HTTP2_HEADER_ETAG,
|
|
11
|
+
HTTP2_HEADER_LAST_MODIFIED
|
|
12
|
+
} = http2.constants
|
|
7
13
|
|
|
8
14
|
const { HTTP_STATUS_PRECONDITION_FAILED } = http2.constants
|
|
9
15
|
|
|
10
16
|
/**
|
|
11
17
|
* @param {ServerHttp2Stream} stream
|
|
18
|
+
* @param {Pick<SendContent, 'etag' | 'lastModified'>} content
|
|
12
19
|
* @param {Metadata} meta
|
|
13
20
|
*/
|
|
14
|
-
export function sendPreconditionFailed(stream, meta) {
|
|
15
|
-
|
|
21
|
+
export function sendPreconditionFailed(stream, content, meta) {
|
|
22
|
+
const {
|
|
23
|
+
etag,
|
|
24
|
+
lastModified
|
|
25
|
+
} = content
|
|
26
|
+
|
|
27
|
+
send(stream, HTTP_STATUS_PRECONDITION_FAILED, {
|
|
28
|
+
[HTTP2_HEADER_ETAG]: Conditional.encodeEtag(etag),
|
|
29
|
+
[HTTP2_HEADER_LAST_MODIFIED]: Conditional.encodeFixDate(lastModified)
|
|
30
|
+
}, [], undefined, undefined, meta)
|
|
16
31
|
}
|
|
@@ -4,7 +4,7 @@ import { CONTENT_RANGE_UNKNOWN, ContentRange } from '../../headers/content-range
|
|
|
4
4
|
import { send } from '../send-util.js'
|
|
5
5
|
|
|
6
6
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
7
|
-
/** @import { Metadata } from '../../defs.js' */
|
|
7
|
+
/** @import { SendContent, Metadata } from '../../defs.js' */
|
|
8
8
|
/** @import { ContentRangeDirective} from '../../headers/content-range.js' */
|
|
9
9
|
|
|
10
10
|
const {
|
|
@@ -15,10 +15,12 @@ const { HTTP_STATUS_RANGE_NOT_SATISFIABLE } = http2.constants
|
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* @param {ServerHttp2Stream} stream
|
|
18
|
-
* @param {
|
|
18
|
+
* @param {Pick<SendContent, 'rangeDirective'>} content
|
|
19
19
|
* @param {Metadata} meta
|
|
20
20
|
*/
|
|
21
|
-
export function sendRangeNotSatisfiable(stream,
|
|
21
|
+
export function sendRangeNotSatisfiable(stream, content, meta) {
|
|
22
|
+
const { rangeDirective } = content
|
|
23
|
+
|
|
22
24
|
/** @type {ContentRangeDirective} */
|
|
23
25
|
const invalidRange = { size: rangeDirective.size, range: CONTENT_RANGE_UNKNOWN }
|
|
24
26
|
|
|
@@ -10,8 +10,7 @@ import {
|
|
|
10
10
|
import { send } from '../send-util.js'
|
|
11
11
|
|
|
12
12
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
13
|
-
/** @import { Metadata } from '../../defs.js' */
|
|
14
|
-
/** @import { RateLimitInfo, RateLimitPolicyInfo } from '../../headers/rate-limit.js' */
|
|
13
|
+
/** @import { SendInfo, Metadata } from '../../defs.js' */
|
|
15
14
|
|
|
16
15
|
const {
|
|
17
16
|
HTTP2_HEADER_RETRY_AFTER
|
|
@@ -21,11 +20,15 @@ const { HTTP_STATUS_TOO_MANY_REQUESTS } = http2.constants
|
|
|
21
20
|
|
|
22
21
|
/**
|
|
23
22
|
* @param {ServerHttp2Stream} stream
|
|
24
|
-
* @param {
|
|
25
|
-
* @param {Array<RateLimitPolicyInfo>} policies
|
|
23
|
+
* @param {Pick<SendInfo, 'limitInfo' | 'policies'>} info
|
|
26
24
|
* @param {Metadata} meta
|
|
27
25
|
*/
|
|
28
|
-
export function sendTooManyRequests(stream,
|
|
26
|
+
export function sendTooManyRequests(stream, info, meta) {
|
|
27
|
+
const {
|
|
28
|
+
limitInfo,
|
|
29
|
+
policies
|
|
30
|
+
} = info
|
|
31
|
+
|
|
29
32
|
send(stream, HTTP_STATUS_TOO_MANY_REQUESTS, {
|
|
30
33
|
[HTTP2_HEADER_RETRY_AFTER]: `${limitInfo.resetSeconds}`,
|
|
31
34
|
[HTTP_HEADER_RATE_LIMIT]: RateLimit.from(limitInfo),
|
|
@@ -20,6 +20,6 @@ const { HTTP_STATUS_UNAUTHORIZED } = http2.constants
|
|
|
20
20
|
*/
|
|
21
21
|
export function sendUnauthorized(stream, challenge, meta) {
|
|
22
22
|
send(stream, HTTP_STATUS_UNAUTHORIZED, {
|
|
23
|
-
[HTTP2_HEADER_WWW_AUTHENTICATE]: challenge?.map(Challenge.encode),
|
|
23
|
+
[HTTP2_HEADER_WWW_AUTHENTICATE]: challenge?.map(Challenge.encode), // todo stringify ?
|
|
24
24
|
}, [ HTTP2_HEADER_WWW_AUTHENTICATE ], undefined, undefined, meta)
|
|
25
25
|
}
|
|
@@ -4,7 +4,7 @@ import { HTTP_HEADER_ACCEPT_PATCH, HTTP_HEADER_ACCEPT_POST, HTTP_HEADER_ACCEPT_Q
|
|
|
4
4
|
import { send } from '../send-util.js'
|
|
5
5
|
|
|
6
6
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
7
|
-
/** @import { Metadata } from '../../defs.js' */
|
|
7
|
+
/** @import { SendInfo, Metadata } from '../../defs.js' */
|
|
8
8
|
|
|
9
9
|
const { HTTP2_METHOD_POST, HTTP2_METHOD_PATCH } = http2.constants
|
|
10
10
|
|
|
@@ -12,16 +12,20 @@ const { HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE } = http2.constants
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* @param {ServerHttp2Stream} stream
|
|
15
|
-
* @param {
|
|
16
|
-
* @param {Array<string>|undefined} supportedQueryTypes
|
|
15
|
+
* @param {Pick<SendInfo, 'acceptableMediaType' | 'supportedQueryTypes'>} info
|
|
17
16
|
* @param {Metadata} meta
|
|
18
17
|
*/
|
|
19
|
-
export function sendUnsupportedMediaType(stream,
|
|
18
|
+
export function sendUnsupportedMediaType(stream, info, meta) {
|
|
19
|
+
const {
|
|
20
|
+
supportedQueryTypes,
|
|
21
|
+
acceptableMediaType
|
|
22
|
+
} = info
|
|
23
|
+
|
|
20
24
|
const supportsQuery = supportedQueryTypes !== undefined && supportedQueryTypes.length > 0
|
|
21
25
|
const exposedHeaders = supportsQuery ? [ HTTP_HEADER_ACCEPT_QUERY, HTTP_HEADER_ACCEPT_POST ] : [ HTTP_HEADER_ACCEPT_POST ]
|
|
22
26
|
|
|
23
27
|
const method = HTTP2_METHOD_POST // todo pass in as parameter or split acceptable to post and patch types
|
|
24
|
-
const acceptable = Array.isArray(acceptableMediaType) ? acceptableMediaType : [ acceptableMediaType ]
|
|
28
|
+
const acceptable = Array.isArray(acceptableMediaType) ? acceptableMediaType : [ acceptableMediaType ] // todo undefined creates array of one item
|
|
25
29
|
const acceptHeader = (method === HTTP2_METHOD_POST) ? HTTP_HEADER_ACCEPT_POST : HTTP_HEADER_ACCEPT_PATCH
|
|
26
30
|
const acceptValue = ((method === HTTP2_METHOD_POST) || (method === HTTP2_METHOD_PATCH)) ? acceptable.join(',') : undefined
|
|
27
31
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import http2 from 'node:http2'
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { send } from '../send-util.js'
|
|
3
|
+
import { send_error } from '../send-util.js'
|
|
5
4
|
|
|
6
5
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
7
6
|
/** @import { Metadata } from '../../defs.js' */
|
|
@@ -14,5 +13,5 @@ const { HTTP_STATUS_INTERNAL_SERVER_ERROR } = http2.constants
|
|
|
14
13
|
* @param {Metadata} meta
|
|
15
14
|
*/
|
|
16
15
|
export function sendError(stream, message, meta) {
|
|
17
|
-
|
|
16
|
+
send_error(stream, HTTP_STATUS_INTERNAL_SERVER_ERROR, message, undefined, meta)
|
|
18
17
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import http2 from 'node:http2'
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { send_error } from '../send-util.js'
|
|
4
4
|
|
|
5
5
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
6
6
|
/** @import { Metadata } from '../../defs.js' */
|
|
@@ -12,5 +12,5 @@ const { HTTP_STATUS_INSUFFICIENT_STORAGE } = http2.constants
|
|
|
12
12
|
* @param {Metadata} meta
|
|
13
13
|
*/
|
|
14
14
|
export function sendInsufficientStorage(stream, meta) {
|
|
15
|
-
|
|
15
|
+
send_error(stream, HTTP_STATUS_INSUFFICIENT_STORAGE, 'Insufficient Storage', undefined, meta)
|
|
16
16
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import http2 from 'node:http2'
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { send } from '../send-util.js'
|
|
3
|
+
import { send_error } from '../send-util.js'
|
|
5
4
|
|
|
6
5
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
7
6
|
/** @import { Metadata } from '../../defs.js' */
|
|
@@ -14,5 +13,5 @@ const { HTTP_STATUS_NOT_IMPLEMENTED } = http2.constants
|
|
|
14
13
|
* @param {Metadata} meta
|
|
15
14
|
*/
|
|
16
15
|
export function sendNotImplemented(stream, message, meta) {
|
|
17
|
-
|
|
16
|
+
send_error(stream, HTTP_STATUS_NOT_IMPLEMENTED, message, undefined, meta)
|
|
18
17
|
}
|
|
@@ -1,25 +1,20 @@
|
|
|
1
1
|
import http2 from 'node:http2'
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import { send } from '../send-util.js'
|
|
3
|
+
import { send_error } from '../send-util.js'
|
|
5
4
|
|
|
6
5
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
7
|
-
/** @import { Metadata } from '../../defs.js' */
|
|
8
|
-
|
|
9
|
-
const {
|
|
10
|
-
HTTP2_HEADER_RETRY_AFTER
|
|
11
|
-
} = http2.constants
|
|
6
|
+
/** @import { SendInfo, Metadata } from '../../defs.js' */
|
|
12
7
|
|
|
13
8
|
const { HTTP_STATUS_SERVICE_UNAVAILABLE } = http2.constants
|
|
14
9
|
|
|
15
10
|
/**
|
|
16
11
|
* @param {ServerHttp2Stream} stream
|
|
17
12
|
* @param {string|undefined} message
|
|
18
|
-
* @param {
|
|
13
|
+
* @param {Pick<SendInfo, 'retryAfter'>} info
|
|
19
14
|
* @param {Metadata} meta
|
|
20
15
|
*/
|
|
21
|
-
export function sendUnavailable(stream, message,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
export function sendUnavailable(stream, message, info, meta) {
|
|
17
|
+
const { retryAfter } = info
|
|
18
|
+
|
|
19
|
+
send_error(stream, HTTP_STATUS_SERVICE_UNAVAILABLE, message, retryAfter, meta)
|
|
25
20
|
}
|
|
@@ -27,7 +27,7 @@ const {
|
|
|
27
27
|
* @returns {OutgoingHttpHeaders}
|
|
28
28
|
*/
|
|
29
29
|
export function coreHeaders(status, contentType, exposedHeaders, meta) {
|
|
30
|
-
const exposed = [ HTTP2_HEADER_ETAG, HTTP2_HEADER_SERVER, ...exposedHeaders ]
|
|
30
|
+
const exposed = [ HTTP2_HEADER_ETAG, HTTP2_HEADER_SERVER, ...exposedHeaders ] // todo include lastModified
|
|
31
31
|
|
|
32
32
|
return {
|
|
33
33
|
[HTTP2_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN]: meta.origin,
|
package/src/response/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** biome-ignore-all lint/performance/noBarrelFile: entry point */
|
|
2
2
|
/** biome-ignore-all lint/performance/noReExportAll: entry point */
|
|
3
3
|
export * from '../defs.js'
|
|
4
|
+
export * from './header-util.js'
|
|
4
5
|
export * from './send-util.js'
|
|
5
6
|
// end common headers
|
|
6
7
|
|
|
@@ -13,12 +14,14 @@ export * from './2xx/partial-content.js'
|
|
|
13
14
|
export * from './2xx/preflight.js'
|
|
14
15
|
export * from './2xx/sse.js'
|
|
15
16
|
export * from './2xx/trace.js'
|
|
17
|
+
export * from './3xx/found.js'
|
|
16
18
|
export * from './3xx/moved-permanently.js'
|
|
17
19
|
export * from './3xx/multiple-choices.js'
|
|
18
20
|
export * from './3xx/not-modified.js'
|
|
19
21
|
export * from './3xx/permanent-redirect.js'
|
|
20
22
|
export * from './3xx/see-other.js'
|
|
21
23
|
export * from './3xx/temporary-redirect.js'
|
|
24
|
+
export * from './4xx/bad-request.js'
|
|
22
25
|
export * from './4xx/conflict.js'
|
|
23
26
|
export * from './4xx/content-too-large.js'
|
|
24
27
|
export * from './4xx/forbidden.js'
|
|
@@ -27,6 +30,7 @@ export * from './4xx/im-a-teapot.js'
|
|
|
27
30
|
export * from './4xx/not-acceptable.js'
|
|
28
31
|
export * from './4xx/not-allowed.js'
|
|
29
32
|
export * from './4xx/not-found.js'
|
|
33
|
+
export * from './4xx/payment-required.js'
|
|
30
34
|
export * from './4xx/precondition-failed.js'
|
|
31
35
|
export * from './4xx/range-not-satisfiable.js'
|
|
32
36
|
export * from './4xx/timeout.js'
|