@johntalton/http-util 6.1.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 +2 -1
- package/src/defs.js +1 -1
- package/src/headers/conditional.js +1 -1
- package/src/headers/link.js +1 -1
- package/src/headers/multipart.js +4 -11
- package/src/headers/range.js +2 -0
- package/src/headers/rate-limit.js +1 -1
- package/src/headers/util/mime.js +1 -1
- package/src/headers/util/whitespace.js +1 -1
- package/src/headers/www-authenticate.js +0 -1
- package/src/response/2xx/bytes.js +2 -31
- package/src/response/2xx/created.js +5 -18
- package/src/response/2xx/json.js +6 -19
- package/src/response/2xx/no-content.js +1 -15
- package/src/response/2xx/partial-content.js +1 -28
- package/src/response/2xx/preflight.js +12 -19
- package/src/response/3xx/found.js +5 -3
- package/src/response/3xx/moved-permanently.js +7 -5
- package/src/response/3xx/not-modified.js +2 -21
- 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 +3 -3
- 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 +2 -11
- package/src/response/4xx/not-allowed.js +1 -10
- package/src/response/4xx/payment-required.js +1 -1
- package/src/response/4xx/precondition-failed.js +1 -15
- package/src/response/4xx/range-not-satisfiable.js +1 -10
- package/src/response/4xx/too-many-requests.js +1 -15
- package/src/response/4xx/unsupported-media.js +1 -14
- 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 +3 -20
- package/src/response/header-util.js +1 -1
- package/src/response/response.js +2 -2
- package/src/response/send-util.js +25 -6
package/README.md
CHANGED
|
@@ -64,7 +64,7 @@ All responders take in a `stream` as well as a metadata object to hint on server
|
|
|
64
64
|
- [`sendGone`](#responsegone)
|
|
65
65
|
- [`sendImATeapot`](#)
|
|
66
66
|
- [`sendInsufficientStorage`](#)
|
|
67
|
-
- [`
|
|
67
|
+
- [`sendJSON`](#responsejson) - Standard Ok response with encoding
|
|
68
68
|
- [`sendMovedPermanently`](#responsemovedpermanently)
|
|
69
69
|
- [`sendMultipleChoices`](#)
|
|
70
70
|
- [`sendNoContent`](#responsenocontent)
|
package/package.json
CHANGED
package/src/defs.js
CHANGED
|
@@ -28,7 +28,7 @@ export const RANGE_UNITS_NONE = 'none'
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
/** @import { TimingsInfo } from './headers/server-timing.js' */
|
|
31
|
-
/** @import { EtagItem, IMFFixDateInput
|
|
31
|
+
/** @import { EtagItem, IMFFixDateInput } from './headers/conditional.js' */
|
|
32
32
|
/** @import { CacheControlOptions } from './headers/cache-control.js' */
|
|
33
33
|
/** @import { ContentRangeDirective } from './headers/content-range.js' */
|
|
34
34
|
/** @import { RateLimitPolicyInfo, RateLimitInfo } from './headers/rate-limit.js' */
|
|
@@ -102,7 +102,7 @@ export class ETag {
|
|
|
102
102
|
static isValid(etag) {
|
|
103
103
|
if(etag === undefined) { return false }
|
|
104
104
|
|
|
105
|
-
// %x21 / %x23-7E
|
|
105
|
+
// %x21 / %x23-7E and %x80-FF
|
|
106
106
|
for(const c of etag) {
|
|
107
107
|
if(c.charCodeAt(0) < 0x21) { return false }
|
|
108
108
|
if(c.charCodeAt(0) > 0xFF) { return false }
|
package/src/headers/link.js
CHANGED
package/src/headers/multipart.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { ReadableStream } from 'node:stream/web'
|
|
2
2
|
|
|
3
|
-
import { isQuoted, stripQuotes } from '../headers/util/quote.js'
|
|
4
3
|
import { ContentDisposition } from './content-disposition.js'
|
|
5
4
|
import { ContentRange } from './content-range.js'
|
|
6
5
|
import { ContentType } from './content-type.js'
|
|
@@ -65,11 +64,6 @@ export class Multipart {
|
|
|
65
64
|
|
|
66
65
|
const lines = text.split(MULTIPART_SEPARATOR)
|
|
67
66
|
|
|
68
|
-
if(lines.length === 0) {
|
|
69
|
-
// missing body?
|
|
70
|
-
return formData
|
|
71
|
-
}
|
|
72
|
-
|
|
73
67
|
const boundaryBegin = `${BOUNDARY_MARK}${boundary}`
|
|
74
68
|
const boundaryEnd = `${BOUNDARY_MARK}${boundary}${BOUNDARY_MARK}`
|
|
75
69
|
|
|
@@ -107,7 +101,7 @@ export class Multipart {
|
|
|
107
101
|
throw new Error('disposition not form-data')
|
|
108
102
|
}
|
|
109
103
|
|
|
110
|
-
partName =
|
|
104
|
+
partName = disposition.name
|
|
111
105
|
}
|
|
112
106
|
else {
|
|
113
107
|
// unsupported part header - ignore
|
|
@@ -131,10 +125,9 @@ export class Multipart {
|
|
|
131
125
|
}
|
|
132
126
|
state = MULTIPART_STATE.HEADERS
|
|
133
127
|
}
|
|
134
|
-
else {
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
|
|
128
|
+
// else {
|
|
129
|
+
// throw new Error('unknown state')
|
|
130
|
+
// }
|
|
138
131
|
}
|
|
139
132
|
|
|
140
133
|
return formData
|
package/src/headers/range.js
CHANGED
|
@@ -99,6 +99,8 @@ export class Range {
|
|
|
99
99
|
*/
|
|
100
100
|
static normalize(directive, contentLength) {
|
|
101
101
|
if(directive === undefined) { return undefined }
|
|
102
|
+
if(!Number.isInteger(contentLength)) { return undefined }
|
|
103
|
+
if(contentLength <= 0) { return undefined }
|
|
102
104
|
|
|
103
105
|
/** @type {Array<NormalizedRangeValue>} */
|
|
104
106
|
const normalizedRanges = directive.ranges.map(({ start, end }) => {
|
package/src/headers/util/mime.js
CHANGED
|
@@ -3,39 +3,10 @@ import http2 from 'node:http2'
|
|
|
3
3
|
import { send_bytes } from '../send-util.js'
|
|
4
4
|
|
|
5
5
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
6
|
-
/** @import {
|
|
7
|
-
/** @import { EtagItem, IMFFixDateInput } from '../../headers/conditional.js' */
|
|
8
|
-
/** @import { CacheControlOptions } from '../../headers/cache-control.js' */
|
|
6
|
+
/** @import { SendContent, SendInfo, Metadata, SendBody } from '../../defs.js' */
|
|
9
7
|
|
|
10
8
|
const { HTTP_STATUS_OK } = http2.constants
|
|
11
9
|
|
|
12
|
-
/**
|
|
13
|
-
* @param {ServerHttp2Stream} stream
|
|
14
|
-
* @param {SendBody|undefined} obj
|
|
15
|
-
* @param {string|undefined} contentType
|
|
16
|
-
* @param {number|undefined} contentLength
|
|
17
|
-
* @param {string|undefined} encoding
|
|
18
|
-
* @param {EtagItem|undefined} etag
|
|
19
|
-
* @param {IMFFixDateInput|string|undefined} lastModified
|
|
20
|
-
* @param {number|undefined} age
|
|
21
|
-
* @param {CacheControlOptions} cacheControl
|
|
22
|
-
* @param {AcceptRangeUnits|undefined} acceptRanges
|
|
23
|
-
* @param {Metadata} meta
|
|
24
|
-
*/
|
|
25
|
-
export function sendBytes(stream, contentType, obj, contentLength, encoding, etag, lastModified, age, cacheControl, acceptRanges, meta) {
|
|
26
|
-
_sendBytes(stream, obj, {
|
|
27
|
-
contentType,
|
|
28
|
-
contentLength,
|
|
29
|
-
encoding,
|
|
30
|
-
etag,
|
|
31
|
-
lastModified,
|
|
32
|
-
age,
|
|
33
|
-
cacheControl
|
|
34
|
-
}, {
|
|
35
|
-
acceptRanges
|
|
36
|
-
}, meta)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
10
|
/**
|
|
40
11
|
* @param {ServerHttp2Stream} stream
|
|
41
12
|
* @param {SendBody|undefined} obj
|
|
@@ -43,7 +14,7 @@ export function sendBytes(stream, contentType, obj, contentLength, encoding, eta
|
|
|
43
14
|
* @param {Pick<SendInfo, 'acceptRanges'>} info
|
|
44
15
|
* @param {Metadata} meta
|
|
45
16
|
*/
|
|
46
|
-
export function
|
|
17
|
+
export function sendBytes(stream, obj, content, info, meta) {
|
|
47
18
|
const {
|
|
48
19
|
contentType,
|
|
49
20
|
contentLength,
|
|
@@ -5,7 +5,6 @@ import { send } from '../send-util.js'
|
|
|
5
5
|
|
|
6
6
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
7
7
|
/** @import { SendContent, Metadata } from '../../defs.js' */
|
|
8
|
-
/** @import { EtagItem, IMFFixDateInput } from '../../headers/conditional.js' */
|
|
9
8
|
|
|
10
9
|
const {
|
|
11
10
|
HTTP2_HEADER_LOCATION,
|
|
@@ -17,32 +16,20 @@ const { HTTP_STATUS_CREATED } = http2.constants
|
|
|
17
16
|
|
|
18
17
|
/**
|
|
19
18
|
* @param {ServerHttp2Stream} stream
|
|
20
|
-
* @param {URL} location
|
|
21
|
-
* @param {EtagItem|undefined} etag
|
|
22
|
-
* @param {IMFFixDateInput|string|undefined} lastModified
|
|
23
|
-
* @param {Metadata} meta
|
|
24
|
-
*/
|
|
25
|
-
export function sendCreated(stream, location, etag, lastModified, meta) {
|
|
26
|
-
_sendCreated(stream, location, {
|
|
27
|
-
etag,
|
|
28
|
-
lastModified
|
|
29
|
-
}, meta)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* @param {ServerHttp2Stream} stream
|
|
34
|
-
* @param {URL} location
|
|
19
|
+
* @param {URL|string} location
|
|
35
20
|
* @param {Pick<SendContent, 'etag' | 'lastModified'>} content
|
|
36
21
|
* @param {Metadata} meta
|
|
37
22
|
*/
|
|
38
|
-
export function
|
|
23
|
+
export function sendCreated(stream, location, content, meta) {
|
|
39
24
|
const {
|
|
40
25
|
etag,
|
|
41
26
|
lastModified
|
|
42
27
|
} = content
|
|
43
28
|
|
|
29
|
+
const loc = (location instanceof URL) ? location.href : location
|
|
30
|
+
|
|
44
31
|
send(stream, HTTP_STATUS_CREATED, {
|
|
45
|
-
[HTTP2_HEADER_LOCATION]:
|
|
32
|
+
[HTTP2_HEADER_LOCATION]: loc,
|
|
46
33
|
[HTTP2_HEADER_ETAG]: Conditional.encodeEtag(etag),
|
|
47
34
|
[HTTP2_HEADER_LAST_MODIFIED]: Conditional.encodeFixDate(lastModified)
|
|
48
35
|
}, [ HTTP2_HEADER_LOCATION ], undefined, undefined, meta)
|
package/src/response/2xx/json.js
CHANGED
|
@@ -5,32 +5,19 @@ import { send_encoded } from '../send-util.js'
|
|
|
5
5
|
|
|
6
6
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
7
7
|
/** @import { SendContent, SendInfo, Metadata } from '../../defs.js' */
|
|
8
|
-
/** @import { EtagItem, IMFFixDateInput } from '../../headers/conditional.js' */
|
|
9
|
-
/** @import { CacheControlOptions } from '../../headers/cache-control.js' */
|
|
10
8
|
|
|
11
9
|
const { HTTP_STATUS_OK } = http2.constants
|
|
12
10
|
|
|
13
11
|
/**
|
|
12
|
+
* @deprecated
|
|
14
13
|
* @param {ServerHttp2Stream} stream
|
|
15
14
|
* @param {Object} obj
|
|
16
|
-
* @param {
|
|
17
|
-
* @param {
|
|
18
|
-
* @param {IMFFixDateInput|string|undefined} lastModified
|
|
19
|
-
* @param {number|undefined} age
|
|
20
|
-
* @param {CacheControlOptions} cacheControl
|
|
21
|
-
* @param {Array<string>|undefined} supportedQueryTypes
|
|
15
|
+
* @param {Omit<SendContent, 'contentType' | 'contentLength' | 'rangeDirective'>} content
|
|
16
|
+
* @param {Pick<SendInfo, 'supportedQueryTypes'>} info
|
|
22
17
|
* @param {Metadata} meta
|
|
23
18
|
*/
|
|
24
|
-
export function sendJSON_Encoded(stream, obj,
|
|
25
|
-
|
|
26
|
-
encoding,
|
|
27
|
-
etag,
|
|
28
|
-
lastModified,
|
|
29
|
-
age,
|
|
30
|
-
cacheControl
|
|
31
|
-
}, {
|
|
32
|
-
supportedQueryTypes
|
|
33
|
-
}, meta)
|
|
19
|
+
export function sendJSON_Encoded(stream, obj, content, info, meta) {
|
|
20
|
+
sendJSON(stream, obj, content, info, meta)
|
|
34
21
|
}
|
|
35
22
|
|
|
36
23
|
/**
|
|
@@ -40,7 +27,7 @@ export function sendJSON_Encoded(stream, obj, encoding, etag, lastModified, age,
|
|
|
40
27
|
* @param {Pick<SendInfo, 'supportedQueryTypes'>} info
|
|
41
28
|
* @param {Metadata} meta
|
|
42
29
|
*/
|
|
43
|
-
export function
|
|
30
|
+
export function sendJSON(stream, obj, content, info, meta) {
|
|
44
31
|
const {
|
|
45
32
|
encoding,
|
|
46
33
|
etag,
|
|
@@ -5,7 +5,6 @@ import { send } from '../send-util.js'
|
|
|
5
5
|
|
|
6
6
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
7
7
|
/** @import { SendContent, Metadata } from '../../defs.js' */
|
|
8
|
-
/** @import { EtagItem, IMFFixDateInput } from '../../headers/conditional.js' */
|
|
9
8
|
|
|
10
9
|
const {
|
|
11
10
|
HTTP2_HEADER_ETAG,
|
|
@@ -14,25 +13,12 @@ const {
|
|
|
14
13
|
|
|
15
14
|
const { HTTP_STATUS_NO_CONTENT } = http2.constants
|
|
16
15
|
|
|
17
|
-
/**
|
|
18
|
-
* @param {ServerHttp2Stream} stream
|
|
19
|
-
* @param {EtagItem|undefined} etag
|
|
20
|
-
* @param {IMFFixDateInput|string|undefined} lastModified
|
|
21
|
-
* @param {Metadata} meta
|
|
22
|
-
*/
|
|
23
|
-
export function sendNoContent(stream, etag, lastModified, meta) {
|
|
24
|
-
_sendNoContent(stream, {
|
|
25
|
-
etag,
|
|
26
|
-
lastModified
|
|
27
|
-
}, meta)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
16
|
/**
|
|
31
17
|
* @param {ServerHttp2Stream} stream
|
|
32
18
|
* @param {Pick<SendContent, 'etag' | 'lastModified'>} content
|
|
33
19
|
* @param {Metadata} meta
|
|
34
20
|
*/
|
|
35
|
-
export function
|
|
21
|
+
export function sendNoContent(stream, content, meta) {
|
|
36
22
|
const {
|
|
37
23
|
etag,
|
|
38
24
|
lastModified
|
|
@@ -7,11 +7,8 @@ import { send_bytes } from '../send-util.js'
|
|
|
7
7
|
|
|
8
8
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
9
9
|
/** @import { SendContent, Metadata, SendBody } from '../../defs.js' */
|
|
10
|
-
/** @import { EtagItem, IMFFixDateInput } from '../../headers/conditional.js' */
|
|
11
|
-
/** @import { CacheControlOptions } from '../../headers/cache-control.js' */
|
|
12
10
|
/** @import { ContentRangeDirective } from '../../headers/content-range.js' */
|
|
13
11
|
|
|
14
|
-
|
|
15
12
|
const { HTTP_STATUS_PARTIAL_CONTENT } = http2.constants
|
|
16
13
|
|
|
17
14
|
/**
|
|
@@ -25,37 +22,13 @@ const { HTTP_STATUS_PARTIAL_CONTENT } = http2.constants
|
|
|
25
22
|
* @property {ContentRangeDirective} range
|
|
26
23
|
*/
|
|
27
24
|
|
|
28
|
-
/**
|
|
29
|
-
* @param {ServerHttp2Stream} stream
|
|
30
|
-
* @param {string|undefined} contentType
|
|
31
|
-
* @param {NonEmptyArray<PartialBytes>|PartialBytes} objs
|
|
32
|
-
* @param {number|undefined} contentLength
|
|
33
|
-
* @param {string|undefined} encoding
|
|
34
|
-
* @param {EtagItem|undefined} etag
|
|
35
|
-
* @param {IMFFixDateInput|string|undefined} lastModified
|
|
36
|
-
* @param {number|undefined} age
|
|
37
|
-
* @param {CacheControlOptions} cacheControl
|
|
38
|
-
* @param {Metadata} meta
|
|
39
|
-
*/
|
|
40
|
-
export function sendPartialContent(stream, contentType, objs, contentLength, encoding, etag, lastModified, age, cacheControl, meta) {
|
|
41
|
-
return _sendPartialContent(stream, objs, {
|
|
42
|
-
contentType,
|
|
43
|
-
contentLength,
|
|
44
|
-
encoding,
|
|
45
|
-
etag,
|
|
46
|
-
lastModified,
|
|
47
|
-
age,
|
|
48
|
-
cacheControl
|
|
49
|
-
}, meta)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
25
|
/**
|
|
53
26
|
* @param {ServerHttp2Stream} stream
|
|
54
27
|
* @param {NonEmptyArray<PartialBytes>|PartialBytes} objs
|
|
55
28
|
* @param {Omit<SendContent, 'rangeDirective'>} content
|
|
56
29
|
* @param {Metadata} meta
|
|
57
30
|
*/
|
|
58
|
-
export function
|
|
31
|
+
export function sendPartialContent(stream, objs, content, meta) {
|
|
59
32
|
const {
|
|
60
33
|
contentType,
|
|
61
34
|
contentLength,
|
|
@@ -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 {
|
|
15
|
+
/** @import { SendInfo, Metadata } from '../../defs.js' */
|
|
13
16
|
|
|
14
17
|
const {
|
|
15
18
|
HTTP2_HEADER_CONTENT_TYPE,
|
|
@@ -25,27 +28,12 @@ const {
|
|
|
25
28
|
|
|
26
29
|
const { HTTP_STATUS_OK } = http2.constants
|
|
27
30
|
|
|
28
|
-
/**
|
|
29
|
-
* @param {ServerHttp2Stream} stream
|
|
30
|
-
* @param {Array<string>} supportedMethods
|
|
31
|
-
* @param {Array<string>|undefined} supportedQueryTypes
|
|
32
|
-
* @param {AcceptRangeUnits|undefined} acceptRanges
|
|
33
|
-
* @param {Metadata} meta
|
|
34
|
-
*/
|
|
35
|
-
export function sendPreflight(stream, supportedMethods, supportedQueryTypes, acceptRanges, meta) {
|
|
36
|
-
_sendPreflight(stream, {
|
|
37
|
-
supportedMethods,
|
|
38
|
-
supportedQueryTypes,
|
|
39
|
-
acceptRanges
|
|
40
|
-
}, meta)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
31
|
/**
|
|
44
32
|
* @param {ServerHttp2Stream} stream
|
|
45
33
|
* @param {Pick<SendInfo, 'supportedMethods' | 'supportedQueryTypes' | 'acceptRanges'>} info
|
|
46
34
|
* @param {Metadata} meta
|
|
47
35
|
*/
|
|
48
|
-
export function
|
|
36
|
+
export function sendPreflight(stream, info, meta) {
|
|
49
37
|
const {
|
|
50
38
|
supportedMethods,
|
|
51
39
|
supportedQueryTypes,
|
|
@@ -56,17 +44,22 @@ export function _sendPreflight(stream, info, meta) {
|
|
|
56
44
|
const exposedHeadersAcceptQuery = supportsQuery ? [ HTTP_HEADER_ACCEPT_QUERY ] : []
|
|
57
45
|
const exposedHeaders = acceptRanges === undefined ? exposedHeadersAcceptQuery : [ HTTP2_HEADER_ACCEPT_RANGES, ...exposedHeadersAcceptQuery ]
|
|
58
46
|
|
|
47
|
+
// todo: if supportedMethods includes POST | PATCH
|
|
48
|
+
// include accept-post / accept-patch headers
|
|
49
|
+
|
|
59
50
|
send(stream, HTTP_STATUS_OK, {
|
|
60
51
|
[HTTP2_HEADER_ACCESS_CONTROL_ALLOW_METHODS]: supportedMethods.join(','),
|
|
61
52
|
[HTTP2_HEADER_ACCESS_CONTROL_ALLOW_HEADERS]: [
|
|
62
53
|
HTTP2_HEADER_IF_MATCH,
|
|
63
54
|
HTTP2_HEADER_IF_NONE_MATCH,
|
|
64
55
|
HTTP2_HEADER_AUTHORIZATION,
|
|
65
|
-
HTTP2_HEADER_CONTENT_TYPE,
|
|
66
|
-
HTTP2_HEADER_RANGE,
|
|
56
|
+
HTTP2_HEADER_CONTENT_TYPE, // overrides cors safe restriction (for json)
|
|
57
|
+
HTTP2_HEADER_RANGE, // todo cors safe override not needed
|
|
67
58
|
HTTP2_HEADER_IF_RANGE
|
|
68
59
|
].join(','),
|
|
69
60
|
[HTTP2_HEADER_ACCESS_CONTROL_MAX_AGE]: PREFLIGHT_AGE_SECONDS,
|
|
61
|
+
// [HTTP_HEADER_ACCEPT_POST]: ,
|
|
62
|
+
// [HTTP_HEADER_ACCEPT_PATCH]: ,
|
|
70
63
|
[HTTP2_HEADER_ACCEPT_RANGES]: acceptRanges,
|
|
71
64
|
[HTTP_HEADER_ACCEPT_QUERY]: supportedQueryTypes?.join(',') // todo should empty array return undef
|
|
72
65
|
// Access-Control-Allow-Credentials
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import http2 from 'node:http2'
|
|
2
2
|
|
|
3
3
|
import { send } from '../send-util.js'
|
|
4
4
|
|
|
@@ -13,11 +13,13 @@ const { HTTP_STATUS_FOUND } = 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 sendFound(stream, location, meta) {
|
|
20
|
+
const loc = (location instanceof URL) ? location.href : location
|
|
21
|
+
|
|
20
22
|
send(stream, HTTP_STATUS_FOUND, {
|
|
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_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
|
}
|
|
@@ -6,8 +6,6 @@ import { send } from '../send-util.js'
|
|
|
6
6
|
|
|
7
7
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
8
8
|
/** @import { SendContent, Metadata } from '../../defs.js' */
|
|
9
|
-
/** @import { EtagItem, IMFFixDateInput } from '../../headers/conditional.js' */
|
|
10
|
-
/** @import { CacheControlOptions } from '../../headers/cache-control.js' */
|
|
11
9
|
|
|
12
10
|
const {
|
|
13
11
|
HTTP2_HEADER_AGE,
|
|
@@ -19,29 +17,12 @@ const {
|
|
|
19
17
|
|
|
20
18
|
const { HTTP_STATUS_NOT_MODIFIED } = http2.constants
|
|
21
19
|
|
|
22
|
-
/**
|
|
23
|
-
* @param {ServerHttp2Stream} stream
|
|
24
|
-
* @param {EtagItem|undefined} etag
|
|
25
|
-
* @param {IMFFixDateInput|string|undefined} lastModified
|
|
26
|
-
* @param {number|undefined} age
|
|
27
|
-
* @param {CacheControlOptions} cacheControl
|
|
28
|
-
* @param {Metadata} meta
|
|
29
|
-
*/
|
|
30
|
-
export function sendNotModified(stream, etag, lastModified, age, cacheControl, meta) {
|
|
31
|
-
_sendNotModified(stream, {
|
|
32
|
-
etag,
|
|
33
|
-
lastModified,
|
|
34
|
-
age,
|
|
35
|
-
cacheControl
|
|
36
|
-
}, meta)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
20
|
/**
|
|
40
21
|
* @param {ServerHttp2Stream} stream
|
|
41
22
|
* @param {Pick<SendContent, 'etag' | 'lastModified' | 'age' | 'cacheControl'>} content
|
|
42
23
|
* @param {Metadata} meta
|
|
43
24
|
*/
|
|
44
|
-
export function
|
|
25
|
+
export function sendNotModified(stream, content, meta) {
|
|
45
26
|
const {
|
|
46
27
|
etag,
|
|
47
28
|
lastModified,
|
|
@@ -54,6 +35,6 @@ export function _sendNotModified(stream, content, meta) {
|
|
|
54
35
|
[HTTP2_HEADER_CACHE_CONTROL]: CacheControl.encode(cacheControl),
|
|
55
36
|
[HTTP2_HEADER_ETAG]: Conditional.encodeEtag(etag),
|
|
56
37
|
[HTTP2_HEADER_LAST_MODIFIED]: Conditional.encodeFixDate(lastModified),
|
|
57
|
-
[HTTP2_HEADER_AGE]: age
|
|
38
|
+
[HTTP2_HEADER_AGE]: Number.isInteger(age) ? `${age}` : undefined
|
|
58
39
|
}, [ HTTP2_HEADER_AGE ], undefined, undefined, meta)
|
|
59
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
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import http2 from 'node:http2'
|
|
2
2
|
|
|
3
3
|
import { CONTENT_TYPE_TEXT } from '../../headers/content-type.js'
|
|
4
4
|
import { send } from '../send-util.js'
|
|
@@ -14,6 +14,6 @@ const { HTTP_STATUS_BAD_REQUEST } = http2.constants
|
|
|
14
14
|
* @param {Metadata} meta
|
|
15
15
|
*/
|
|
16
16
|
export function sendBadRequest(stream, message, meta) {
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
send(stream, HTTP_STATUS_BAD_REQUEST, {
|
|
18
|
+
}, [], CONTENT_TYPE_TEXT, message, meta)
|
|
19
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
|
}
|
|
@@ -8,21 +8,12 @@ import { send } from '../send-util.js'
|
|
|
8
8
|
|
|
9
9
|
const { HTTP_STATUS_NOT_ACCEPTABLE } = http2.constants
|
|
10
10
|
|
|
11
|
-
/**
|
|
12
|
-
* @param {ServerHttp2Stream} stream
|
|
13
|
-
* @param {Array<string>|string} supportedTypes
|
|
14
|
-
* @param {Metadata} meta
|
|
15
|
-
*/
|
|
16
|
-
export function sendNotAcceptable(stream, supportedTypes, meta) {
|
|
17
|
-
_sendNotAcceptable(stream, { supportedTypes }, meta)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
11
|
/**
|
|
21
12
|
* @param {ServerHttp2Stream} stream
|
|
22
13
|
* @param {Pick<SendInfo, 'supportedTypes'>} info
|
|
23
14
|
* @param {Metadata} meta
|
|
24
15
|
*/
|
|
25
|
-
export function
|
|
16
|
+
export function sendNotAcceptable(stream, info, meta) {
|
|
26
17
|
const { supportedTypes } = info
|
|
27
18
|
|
|
28
19
|
const supportedTypesList = Array.isArray(supportedTypes) ? supportedTypes : [ supportedTypes ]
|
|
@@ -33,6 +24,6 @@ export function _sendNotAcceptable(stream, info, meta) {
|
|
|
33
24
|
{},
|
|
34
25
|
[],
|
|
35
26
|
has ? CONTENT_TYPE_JSON : undefined,
|
|
36
|
-
has ? JSON.stringify(supportedTypes) : undefined,
|
|
27
|
+
has ? JSON.stringify({ supportedTypes: supportedTypesList }) : undefined,
|
|
37
28
|
meta)
|
|
38
29
|
}
|
|
@@ -11,21 +11,12 @@ const {
|
|
|
11
11
|
|
|
12
12
|
const { HTTP2_HEADER_ALLOW } = http2.constants
|
|
13
13
|
|
|
14
|
-
/**
|
|
15
|
-
* @param {ServerHttp2Stream} stream
|
|
16
|
-
* @param {Array<string>} supportedMethods
|
|
17
|
-
* @param {Metadata} meta
|
|
18
|
-
*/
|
|
19
|
-
export function sendNotAllowed(stream, supportedMethods, meta) {
|
|
20
|
-
_sendNotAllowed(stream, { supportedMethods }, meta)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
14
|
/**
|
|
24
15
|
* @param {ServerHttp2Stream} stream
|
|
25
16
|
* @param {Pick<SendInfo, 'supportedMethods'>} info
|
|
26
17
|
* @param {Metadata} meta
|
|
27
18
|
*/
|
|
28
|
-
export function
|
|
19
|
+
export function sendNotAllowed(stream, info, meta) {
|
|
29
20
|
const { supportedMethods } = info
|
|
30
21
|
|
|
31
22
|
send(stream, HTTP_STATUS_METHOD_NOT_ALLOWED, {
|
|
@@ -5,7 +5,6 @@ import { send } from '../send-util.js'
|
|
|
5
5
|
|
|
6
6
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
7
7
|
/** @import { SendContent, Metadata } from '../../defs.js' */
|
|
8
|
-
/** @import { EtagItem ,IMFFixDateInput } from '../../headers/conditional.js' */
|
|
9
8
|
|
|
10
9
|
const {
|
|
11
10
|
HTTP2_HEADER_ETAG,
|
|
@@ -14,25 +13,12 @@ const {
|
|
|
14
13
|
|
|
15
14
|
const { HTTP_STATUS_PRECONDITION_FAILED } = http2.constants
|
|
16
15
|
|
|
17
|
-
/**
|
|
18
|
-
* @param {ServerHttp2Stream} stream
|
|
19
|
-
* @param {EtagItem|undefined} etag
|
|
20
|
-
* @param {IMFFixDateInput|string|undefined} lastModified
|
|
21
|
-
* @param {Metadata} meta
|
|
22
|
-
*/
|
|
23
|
-
export function sendPreconditionFailed(stream, etag, lastModified, meta) {
|
|
24
|
-
_sendPreconditionFailed(stream, {
|
|
25
|
-
etag,
|
|
26
|
-
lastModified
|
|
27
|
-
}, meta)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
16
|
/**
|
|
31
17
|
* @param {ServerHttp2Stream} stream
|
|
32
18
|
* @param {Pick<SendContent, 'etag' | 'lastModified'>} content
|
|
33
19
|
* @param {Metadata} meta
|
|
34
20
|
*/
|
|
35
|
-
export function
|
|
21
|
+
export function sendPreconditionFailed(stream, content, meta) {
|
|
36
22
|
const {
|
|
37
23
|
etag,
|
|
38
24
|
lastModified
|
|
@@ -13,21 +13,12 @@ const {
|
|
|
13
13
|
|
|
14
14
|
const { HTTP_STATUS_RANGE_NOT_SATISFIABLE } = http2.constants
|
|
15
15
|
|
|
16
|
-
/**
|
|
17
|
-
* @param {ServerHttp2Stream} stream
|
|
18
|
-
* @param {ContentRangeDirective} rangeDirective
|
|
19
|
-
* @param {Metadata} meta
|
|
20
|
-
*/
|
|
21
|
-
export function sendRangeNotSatisfiable(stream, rangeDirective, meta) {
|
|
22
|
-
_sendRangeNotSatisfiable(stream, { rangeDirective }, meta)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
16
|
/**
|
|
26
17
|
* @param {ServerHttp2Stream} stream
|
|
27
18
|
* @param {Pick<SendContent, 'rangeDirective'>} content
|
|
28
19
|
* @param {Metadata} meta
|
|
29
20
|
*/
|
|
30
|
-
export function
|
|
21
|
+
export function sendRangeNotSatisfiable(stream, content, meta) {
|
|
31
22
|
const { rangeDirective } = content
|
|
32
23
|
|
|
33
24
|
/** @type {ContentRangeDirective} */
|
|
@@ -11,7 +11,6 @@ import { send } from '../send-util.js'
|
|
|
11
11
|
|
|
12
12
|
/** @import { ServerHttp2Stream } from 'node:http2' */
|
|
13
13
|
/** @import { SendInfo, Metadata } from '../../defs.js' */
|
|
14
|
-
/** @import { RateLimitInfo, RateLimitPolicyInfo } from '../../headers/rate-limit.js' */
|
|
15
14
|
|
|
16
15
|
const {
|
|
17
16
|
HTTP2_HEADER_RETRY_AFTER
|
|
@@ -19,25 +18,12 @@ const {
|
|
|
19
18
|
|
|
20
19
|
const { HTTP_STATUS_TOO_MANY_REQUESTS } = http2.constants
|
|
21
20
|
|
|
22
|
-
/**
|
|
23
|
-
* @param {ServerHttp2Stream} stream
|
|
24
|
-
* @param {RateLimitInfo} limitInfo
|
|
25
|
-
* @param {Array<RateLimitPolicyInfo>} policies
|
|
26
|
-
* @param {Metadata} meta
|
|
27
|
-
*/
|
|
28
|
-
export function sendTooManyRequests(stream, limitInfo, policies, meta) {
|
|
29
|
-
_sendTooManyRequests(stream, {
|
|
30
|
-
limitInfo,
|
|
31
|
-
policies
|
|
32
|
-
}, meta)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
21
|
/**
|
|
36
22
|
* @param {ServerHttp2Stream} stream
|
|
37
23
|
* @param {Pick<SendInfo, 'limitInfo' | 'policies'>} info
|
|
38
24
|
* @param {Metadata} meta
|
|
39
25
|
*/
|
|
40
|
-
export function
|
|
26
|
+
export function sendTooManyRequests(stream, info, meta) {
|
|
41
27
|
const {
|
|
42
28
|
limitInfo,
|
|
43
29
|
policies
|
|
@@ -10,25 +10,12 @@ const { HTTP2_METHOD_POST, HTTP2_METHOD_PATCH } = http2.constants
|
|
|
10
10
|
|
|
11
11
|
const { HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE } = http2.constants
|
|
12
12
|
|
|
13
|
-
/**
|
|
14
|
-
* @param {ServerHttp2Stream} stream
|
|
15
|
-
* @param {Array<string>|string} acceptableMediaType
|
|
16
|
-
* @param {Array<string>|undefined} supportedQueryTypes
|
|
17
|
-
* @param {Metadata} meta
|
|
18
|
-
*/
|
|
19
|
-
export function sendUnsupportedMediaType(stream, acceptableMediaType, supportedQueryTypes, meta) {
|
|
20
|
-
_sendUnsupportedMediaType(stream, {
|
|
21
|
-
acceptableMediaType,
|
|
22
|
-
supportedQueryTypes
|
|
23
|
-
}, meta)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
13
|
/**
|
|
27
14
|
* @param {ServerHttp2Stream} stream
|
|
28
15
|
* @param {Pick<SendInfo, 'acceptableMediaType' | 'supportedQueryTypes'>} info
|
|
29
16
|
* @param {Metadata} meta
|
|
30
17
|
*/
|
|
31
|
-
export function
|
|
18
|
+
export function sendUnsupportedMediaType(stream, info, meta) {
|
|
32
19
|
const {
|
|
33
20
|
supportedQueryTypes,
|
|
34
21
|
acceptableMediaType
|
|
@@ -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,37 +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
6
|
/** @import { SendInfo, Metadata } from '../../defs.js' */
|
|
8
7
|
|
|
9
|
-
const {
|
|
10
|
-
HTTP2_HEADER_RETRY_AFTER
|
|
11
|
-
} = http2.constants
|
|
12
|
-
|
|
13
8
|
const { HTTP_STATUS_SERVICE_UNAVAILABLE } = http2.constants
|
|
14
9
|
|
|
15
|
-
/**
|
|
16
|
-
* @param {ServerHttp2Stream} stream
|
|
17
|
-
* @param {string|undefined} message
|
|
18
|
-
* @param {number|undefined} retryAfter
|
|
19
|
-
* @param {Metadata} meta
|
|
20
|
-
*/
|
|
21
|
-
export function sendUnavailable(stream, message, retryAfter, meta) {
|
|
22
|
-
_sendUnavailable(stream, message, { retryAfter }, meta)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
10
|
/**
|
|
26
11
|
* @param {ServerHttp2Stream} stream
|
|
27
12
|
* @param {string|undefined} message
|
|
28
13
|
* @param {Pick<SendInfo, 'retryAfter'>} info
|
|
29
14
|
* @param {Metadata} meta
|
|
30
15
|
*/
|
|
31
|
-
export function
|
|
16
|
+
export function sendUnavailable(stream, message, info, meta) {
|
|
32
17
|
const { retryAfter } = info
|
|
33
18
|
|
|
34
|
-
|
|
35
|
-
[HTTP2_HEADER_RETRY_AFTER]: Number.isInteger(retryAfter) ? `${retryAfter}` : undefined
|
|
36
|
-
}, [ HTTP2_HEADER_RETRY_AFTER ], CONTENT_TYPE_TEXT, message, meta)
|
|
19
|
+
send_error(stream, HTTP_STATUS_SERVICE_UNAVAILABLE, message, retryAfter, meta)
|
|
37
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/response.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { sendAccepted } from './2xx/accepted.js'
|
|
2
2
|
import { sendBytes } from './2xx/bytes.js'
|
|
3
3
|
import { sendCreated } from './2xx/created.js'
|
|
4
|
-
import {
|
|
4
|
+
import { sendJSON } from './2xx/json.js'
|
|
5
5
|
import { sendNoContent } from './2xx/no-content.js'
|
|
6
6
|
import { sendPartialContent } from './2xx/partial-content.js'
|
|
7
7
|
import { sendPreflight } from './2xx/preflight.js'
|
|
@@ -49,7 +49,7 @@ export const Response = {
|
|
|
49
49
|
gone: sendGone,
|
|
50
50
|
imATeapot: sendImATeapot,
|
|
51
51
|
insufficientStorage: sendInsufficientStorage,
|
|
52
|
-
json:
|
|
52
|
+
json: sendJSON,
|
|
53
53
|
movedPermanently: sendMovedPermanently,
|
|
54
54
|
multipleChoices: sendMultipleChoices,
|
|
55
55
|
noContent: sendNoContent,
|
|
@@ -12,7 +12,7 @@ import { HTTP_HEADER_ACCEPT_QUERY } from '../defs.js'
|
|
|
12
12
|
import { CacheControl } from '../headers/cache-control.js'
|
|
13
13
|
import { Conditional } from '../headers/conditional.js'
|
|
14
14
|
import { ContentRange } from '../headers/content-range.js'
|
|
15
|
-
import { CHARSET_UTF8 } from '../headers/content-type.js'
|
|
15
|
+
import { CHARSET_UTF8, CONTENT_TYPE_JSON } from '../headers/content-type.js'
|
|
16
16
|
import {
|
|
17
17
|
coreHeaders,
|
|
18
18
|
customHeaders,
|
|
@@ -45,9 +45,29 @@ const {
|
|
|
45
45
|
HTTP2_HEADER_CONTENT_LENGTH,
|
|
46
46
|
HTTP2_HEADER_ACCEPT,
|
|
47
47
|
HTTP2_HEADER_ACCEPT_ENCODING,
|
|
48
|
-
HTTP2_HEADER_RANGE
|
|
48
|
+
HTTP2_HEADER_RANGE,
|
|
49
|
+
HTTP2_HEADER_RETRY_AFTER
|
|
49
50
|
} = http2.constants
|
|
50
51
|
|
|
52
|
+
/**
|
|
53
|
+
* @param {ServerHttp2Stream} stream
|
|
54
|
+
* @param {number} status
|
|
55
|
+
* @param {string|undefined} message
|
|
56
|
+
* @param {number|undefined} retryAfter
|
|
57
|
+
* @param {Metadata} meta
|
|
58
|
+
*/
|
|
59
|
+
export function send_error(stream, status, message, retryAfter, meta) {
|
|
60
|
+
const obj = JSON.stringify({
|
|
61
|
+
message: message ?? 'Error'
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
const exposedHeaders = Number.isInteger(retryAfter) ? [ HTTP2_HEADER_RETRY_AFTER ] : []
|
|
65
|
+
|
|
66
|
+
send(stream, status, {
|
|
67
|
+
[HTTP2_HEADER_RETRY_AFTER]: Number.isInteger(retryAfter) ? `${retryAfter}` : undefined
|
|
68
|
+
}, exposedHeaders, CONTENT_TYPE_JSON, obj, meta) // todo should this be plain text
|
|
69
|
+
}
|
|
70
|
+
|
|
51
71
|
/** @typedef { (data: InputType) => Buffer<ArrayBuffer> } EncoderFun */
|
|
52
72
|
|
|
53
73
|
/** @type {Map<string, EncoderFun>} */
|
|
@@ -91,7 +111,6 @@ export function send_encoded(stream, status, contentType, body, encoding, etag,
|
|
|
91
111
|
send_bytes(stream, status, contentType, encodedData, undefined, undefined, actualEncoding, etag, lastModified, age, cacheControl, acceptRanges, supportedQueryTypes, meta )
|
|
92
112
|
}
|
|
93
113
|
|
|
94
|
-
|
|
95
114
|
/**
|
|
96
115
|
* @param {ServerHttp2Stream} stream
|
|
97
116
|
* @param {number} status
|
|
@@ -127,7 +146,7 @@ export function send_bytes(stream, status, contentType, obj, range, contentLengt
|
|
|
127
146
|
[HTTP2_HEADER_CACHE_CONTROL]: CacheControl.encode(cacheControl),
|
|
128
147
|
[HTTP2_HEADER_ETAG]: Conditional.encodeEtag(etag),
|
|
129
148
|
[HTTP2_HEADER_LAST_MODIFIED]: Conditional.encodeFixDate(lastModified),
|
|
130
|
-
[HTTP2_HEADER_AGE]: age
|
|
149
|
+
[HTTP2_HEADER_AGE]: Number.isInteger(age) ? `${age}` : undefined,
|
|
131
150
|
[HTTP2_HEADER_CONTENT_LENGTH]: contentLen,
|
|
132
151
|
[HTTP2_HEADER_CONTENT_RANGE]: ContentRange.encode(range),
|
|
133
152
|
[HTTP2_HEADER_ACCEPT_RANGES]: acceptRanges,
|
|
@@ -173,8 +192,8 @@ export function send(stream, status, headers, exposedHeaders, contentType, body,
|
|
|
173
192
|
Readable.fromWeb(body, { signal }),
|
|
174
193
|
stream,
|
|
175
194
|
err => {
|
|
176
|
-
if(err !== null) {
|
|
177
|
-
console.warn('pipeline error')
|
|
195
|
+
if(err !== null && err !== undefined) {
|
|
196
|
+
console.warn('pipeline error', err)
|
|
178
197
|
}
|
|
179
198
|
})
|
|
180
199
|
|