@opra/core 1.0.0-beta.2 → 1.0.0-beta.4

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.
Files changed (85) hide show
  1. package/cjs/{http/impl/asset-cache.js → asset-cache.js} +6 -0
  2. package/cjs/execution-context.js +3 -14
  3. package/cjs/index.js +3 -25
  4. package/cjs/platform-adapter.js +3 -3
  5. package/cjs/{helpers/service-base.js → service-base.js} +9 -4
  6. package/esm/{http/impl/asset-cache.js → asset-cache.js} +6 -0
  7. package/esm/execution-context.js +2 -13
  8. package/esm/index.js +3 -24
  9. package/esm/platform-adapter.js +2 -2
  10. package/esm/{helpers/service-base.js → service-base.js} +9 -4
  11. package/package.json +5 -39
  12. package/types/{http/impl/asset-cache.d.ts → asset-cache.d.ts} +1 -0
  13. package/types/execution-context.d.ts +4 -8
  14. package/types/index.d.cts +3 -23
  15. package/types/index.d.ts +3 -23
  16. package/types/interfaces/logger.interface.d.ts +1 -1
  17. package/types/platform-adapter.d.ts +3 -3
  18. package/types/service-base.d.ts +11 -0
  19. package/cjs/augmentation/http-controller.augmentation.js +0 -25
  20. package/cjs/http/express-adapter.js +0 -155
  21. package/cjs/http/http-adapter.js +0 -24
  22. package/cjs/http/http-context.js +0 -104
  23. package/cjs/http/http-handler.js +0 -609
  24. package/cjs/http/impl/http-incoming.host.js +0 -112
  25. package/cjs/http/impl/http-outgoing.host.js +0 -207
  26. package/cjs/http/impl/multipart-reader.js +0 -196
  27. package/cjs/http/impl/node-incoming-message.host.js +0 -109
  28. package/cjs/http/impl/node-outgoing-message.host.js +0 -195
  29. package/cjs/http/interfaces/http-incoming.interface.js +0 -25
  30. package/cjs/http/interfaces/http-outgoing.interface.js +0 -22
  31. package/cjs/http/interfaces/node-incoming-message.interface.js +0 -64
  32. package/cjs/http/interfaces/node-outgoing-message.interface.js +0 -15
  33. package/cjs/http/utils/body-reader.js +0 -216
  34. package/cjs/http/utils/common.js +0 -67
  35. package/cjs/http/utils/concat-readable.js +0 -19
  36. package/cjs/http/utils/convert-to-headers.js +0 -64
  37. package/cjs/http/utils/convert-to-raw-headers.js +0 -23
  38. package/cjs/http/utils/match-known-fields.js +0 -49
  39. package/cjs/http/utils/wrap-exception.js +0 -33
  40. package/cjs/type-guards.js +0 -22
  41. package/esm/augmentation/http-controller.augmentation.js +0 -23
  42. package/esm/http/express-adapter.js +0 -150
  43. package/esm/http/http-adapter.js +0 -20
  44. package/esm/http/http-context.js +0 -99
  45. package/esm/http/http-handler.js +0 -604
  46. package/esm/http/impl/http-incoming.host.js +0 -107
  47. package/esm/http/impl/http-outgoing.host.js +0 -202
  48. package/esm/http/impl/multipart-reader.js +0 -191
  49. package/esm/http/impl/node-incoming-message.host.js +0 -105
  50. package/esm/http/impl/node-outgoing-message.host.js +0 -191
  51. package/esm/http/interfaces/http-incoming.interface.js +0 -22
  52. package/esm/http/interfaces/http-outgoing.interface.js +0 -19
  53. package/esm/http/interfaces/node-incoming-message.interface.js +0 -61
  54. package/esm/http/interfaces/node-outgoing-message.interface.js +0 -12
  55. package/esm/http/utils/body-reader.js +0 -211
  56. package/esm/http/utils/common.js +0 -61
  57. package/esm/http/utils/concat-readable.js +0 -16
  58. package/esm/http/utils/convert-to-headers.js +0 -60
  59. package/esm/http/utils/convert-to-raw-headers.js +0 -20
  60. package/esm/http/utils/match-known-fields.js +0 -45
  61. package/esm/http/utils/wrap-exception.js +0 -30
  62. package/esm/type-guards.js +0 -16
  63. package/types/augmentation/http-controller.augmentation.d.ts +0 -20
  64. package/types/helpers/service-base.d.ts +0 -10
  65. package/types/http/express-adapter.d.ts +0 -13
  66. package/types/http/http-adapter.d.ts +0 -54
  67. package/types/http/http-context.d.ts +0 -44
  68. package/types/http/http-handler.d.ts +0 -75
  69. package/types/http/impl/http-incoming.host.d.ts +0 -22
  70. package/types/http/impl/http-outgoing.host.d.ts +0 -17
  71. package/types/http/impl/multipart-reader.d.ts +0 -46
  72. package/types/http/impl/node-incoming-message.host.d.ts +0 -45
  73. package/types/http/impl/node-outgoing-message.host.d.ts +0 -49
  74. package/types/http/interfaces/http-incoming.interface.d.ts +0 -192
  75. package/types/http/interfaces/http-outgoing.interface.d.ts +0 -144
  76. package/types/http/interfaces/node-incoming-message.interface.d.ts +0 -36
  77. package/types/http/interfaces/node-outgoing-message.interface.d.ts +0 -27
  78. package/types/http/utils/body-reader.d.ts +0 -38
  79. package/types/http/utils/common.d.ts +0 -17
  80. package/types/http/utils/concat-readable.d.ts +0 -2
  81. package/types/http/utils/convert-to-headers.d.ts +0 -2
  82. package/types/http/utils/convert-to-raw-headers.d.ts +0 -2
  83. package/types/http/utils/match-known-fields.d.ts +0 -6
  84. package/types/http/utils/wrap-exception.d.ts +0 -2
  85. package/types/type-guards.d.ts +0 -8
@@ -1,191 +0,0 @@
1
- /*
2
- This file contains code blocks from open source NodeJs project
3
- https://github.com/nodejs/
4
- */
5
- import { Duplex } from 'stream';
6
- import { validateHeaderName, validateHeaderValue, validateString } from '../utils/common.js';
7
- export const kOutHeaders = Symbol.for('kOutHeaders');
8
- export const kOutTrailers = Symbol.for('kOutTrailers');
9
- // noinspection JSUnusedLocalSymbols
10
- /**
11
- *
12
- * @class NodeOutgoingMessageHost
13
- */
14
- export class NodeOutgoingMessageHost extends Duplex {
15
- constructor(init) {
16
- super();
17
- this._headersSent = false;
18
- this.finished = false;
19
- if (init) {
20
- this.req = init.req;
21
- this.statusCode = init?.statusCode || 0;
22
- this.statusMessage = init?.statusMessage || '';
23
- this.chunkedEncoding = !!init?.chunkedEncoding;
24
- this.sendDate = !!init?.sendDate;
25
- this.strictContentLength = !!init?.strictContentLength;
26
- if (init.headers)
27
- this.setHeaders(Array.isArray(init.headers) ? new Map([init.headers]) : init.headers);
28
- this.body = init.body;
29
- }
30
- }
31
- get httpVersionMajor() {
32
- return this.req?.httpVersionMajor || this._httpVersionMajor;
33
- }
34
- get httpVersionMinor() {
35
- return this.req?.httpVersionMinor || this._httpVersionMinor;
36
- }
37
- get headersSent() {
38
- return this._headersSent;
39
- }
40
- appendHeader(name, value) {
41
- if (this.headersSent)
42
- throw new Error(`Cannot set headers after they are sent to the client`);
43
- validateHeaderName(name);
44
- validateHeaderValue(name, value);
45
- const field = name.toLowerCase();
46
- const headers = this[kOutHeaders];
47
- if (headers == null || !headers[field]) {
48
- return this.setHeader(name, value);
49
- }
50
- // Prepare the field for appending, if required
51
- if (!Array.isArray(headers[field][1])) {
52
- headers[field][1] = [headers[field][1]];
53
- }
54
- const existingValues = headers[field][1];
55
- if (Array.isArray(value)) {
56
- for (let i = 0, length = value.length; i < length; i++) {
57
- existingValues.push(value[i]);
58
- }
59
- }
60
- else {
61
- existingValues.push(value);
62
- }
63
- return this;
64
- }
65
- addTrailers(headers) {
66
- if (headers && typeof headers === 'object') {
67
- const entries = typeof headers.entries === 'function' ? headers.entries() : Object.entries(headers);
68
- let trailers = this[kOutTrailers];
69
- if (trailers == null)
70
- this[kOutTrailers] = trailers = { __proto__: null };
71
- for (const [name, value] of entries) {
72
- validateHeaderName(name);
73
- validateHeaderValue(name, value);
74
- trailers[String(name).toLowerCase()] = [String(name), value];
75
- }
76
- return;
77
- }
78
- throw new TypeError('Invalid "headers" argument. Value must be an object or raw headers array');
79
- }
80
- flushHeaders() {
81
- // nothing to do
82
- }
83
- setHeader(name, value) {
84
- if (this.headersSent)
85
- throw new Error(`Cannot set headers after they are sent to the client`);
86
- validateHeaderName(name);
87
- validateHeaderValue(name, value);
88
- let headers = this[kOutHeaders];
89
- if (headers == null)
90
- this[kOutHeaders] = headers = { __proto__: null };
91
- headers[name.toLowerCase()] = [name, value];
92
- return this;
93
- }
94
- setHeaders(headers) {
95
- if (this.headersSent)
96
- throw new Error(`Cannot set headers after they are sent to the client`);
97
- if (headers && typeof headers === 'object' && !Array.isArray(headers)) {
98
- const entries = typeof headers.entries === 'function' ? headers.entries() : Object.entries(headers);
99
- for (const entry of entries) {
100
- this.setHeader(entry[0], entry[1]);
101
- }
102
- return this;
103
- }
104
- throw new TypeError('Invalid "headers" argument. Value must be an instance of "Headers" or "Map"');
105
- }
106
- getHeader(name) {
107
- validateString(name);
108
- const headers = this[kOutHeaders];
109
- if (headers == null)
110
- return;
111
- const entry = headers[name.toLowerCase()];
112
- return entry && entry[1];
113
- }
114
- getHeaderNames() {
115
- return this[kOutHeaders] != null ? Object.keys(this[kOutHeaders]) : [];
116
- }
117
- getRawHeaderNames() {
118
- const headersMap = this[kOutHeaders];
119
- if (!headersMap)
120
- return [];
121
- const values = Object.values(headersMap);
122
- const headers = Array(values.length);
123
- for (let i = 0, l = values.length; i < l; i++) {
124
- headers[i] = values[i][0];
125
- }
126
- return headers;
127
- }
128
- getHeaders() {
129
- const headers = this[kOutHeaders];
130
- // @ts-ignore
131
- const ret = { __proto__: null };
132
- if (headers) {
133
- const keys = Object.keys(headers);
134
- let key;
135
- let val;
136
- for (let i = 0; i < keys.length; ++i) {
137
- key = keys[i];
138
- val = headers[key][1];
139
- ret[key] = val;
140
- }
141
- }
142
- return ret;
143
- }
144
- hasHeader(name) {
145
- validateString(name);
146
- return this[kOutHeaders] != null && !!this[kOutHeaders][name.toLowerCase()];
147
- }
148
- removeHeader(name) {
149
- validateString(name);
150
- if (this.headersSent)
151
- throw new Error(`Cannot remove headers after they are sent to the client`);
152
- const key = name.toLowerCase();
153
- // switch (key) {
154
- // case 'connection':
155
- // this._removedConnection = true;
156
- // break;
157
- // case 'content-length':
158
- // this._removedContLen = true;
159
- // break;
160
- // case 'transfer-encoding':
161
- // this._removedTE = true;
162
- // break;
163
- // case 'date':
164
- // this.sendDate = false;
165
- // break;
166
- // }
167
- if (this[kOutHeaders] != null) {
168
- delete this[kOutHeaders][key];
169
- }
170
- }
171
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
172
- end(arg0, arg1, arg2) {
173
- // let cb: (() => void) | undefined;
174
- // let chunk: any;
175
- // let encoding: BufferEncoding | undefined;
176
- //
177
- // if (typeof arg0 === 'function')
178
- // cb = arg0;
179
- // else {
180
- // chunk = arg0;
181
- // if (typeof arg1 === 'function')
182
- // cb = arg1;
183
- // else {
184
- // encoding = arg1;
185
- // cb = arg2;
186
- // }
187
- // }
188
- //
189
- return this;
190
- }
191
- }
@@ -1,22 +0,0 @@
1
- import { mergePrototype } from '@opra/common';
2
- import { isHttpIncoming, isNodeIncomingMessage } from '../../type-guards.js';
3
- import { HttpIncomingHost } from '../impl/http-incoming.host.js';
4
- import { NodeIncomingMessage } from './node-incoming-message.interface.js';
5
- /**
6
- * @namespace HttpIncoming
7
- */
8
- export var HttpIncoming;
9
- (function (HttpIncoming) {
10
- function from(instance) {
11
- if (isHttpIncoming(instance))
12
- return instance;
13
- if (!isNodeIncomingMessage(instance))
14
- instance = NodeIncomingMessage.from(instance);
15
- mergePrototype(instance, HttpIncomingHost.prototype);
16
- const req = instance;
17
- req.baseUrl = req.baseUrl || '';
18
- req.params = req.params || {};
19
- return req;
20
- }
21
- HttpIncoming.from = from;
22
- })(HttpIncoming || (HttpIncoming = {}));
@@ -1,19 +0,0 @@
1
- import { mergePrototype } from '@opra/common';
2
- import { isHttpOutgoing, isNodeOutgoingMessage } from '../../type-guards.js';
3
- import { HttpOutgoingHost } from '../impl/http-outgoing.host.js';
4
- import { NodeOutgoingMessage } from './node-outgoing-message.interface.js';
5
- /**
6
- * @namespace HttpIncoming
7
- */
8
- export var HttpOutgoing;
9
- (function (HttpOutgoing) {
10
- function from(instance) {
11
- if (isHttpOutgoing(instance))
12
- return instance;
13
- if (!isNodeOutgoingMessage(instance))
14
- instance = NodeOutgoingMessage.from(instance);
15
- mergePrototype(instance, HttpOutgoingHost.prototype);
16
- return instance;
17
- }
18
- HttpOutgoing.from = from;
19
- })(HttpOutgoing || (HttpOutgoing = {}));
@@ -1,61 +0,0 @@
1
- import { HTTPParser } from '@browsery/http-parser';
2
- import { isAsyncIterable, isIterable } from '@opra/common';
3
- import { Readable } from 'stream';
4
- import { CRLF, kHttpParser, NodeIncomingMessageHost } from '../impl/node-incoming-message.host.js';
5
- import { concatReadable } from '../utils/concat-readable.js';
6
- /**
7
- *
8
- * @namespace NodeIncomingMessage
9
- */
10
- export var NodeIncomingMessage;
11
- (function (NodeIncomingMessage) {
12
- /**
13
- * Creates a new NodeIncomingMessage from given argument
14
- * @param iterable
15
- */
16
- function from(iterable) {
17
- if (typeof iterable === 'object' && !(isIterable(iterable) || isAsyncIterable(iterable))) {
18
- return new NodeIncomingMessageHost(iterable);
19
- }
20
- const msg = new NodeIncomingMessageHost();
21
- const parser = (msg[kHttpParser] = new HTTPParser(HTTPParser.REQUEST));
22
- let bodyChunks;
23
- parser[HTTPParser.kOnHeadersComplete] = (info) => {
24
- msg.httpVersionMajor = info.versionMajor;
25
- msg.httpVersionMinor = info.versionMinor;
26
- msg.rawHeaders = info.headers;
27
- msg.method = HTTPParser.methods[info.method];
28
- msg.url = info.url;
29
- msg.emit('headers');
30
- };
31
- parser[HTTPParser.kOnHeaders] = (trailers) => {
32
- msg.rawTrailers = trailers;
33
- };
34
- parser[HTTPParser.kOnBody] = (chunk, offset, length) => {
35
- bodyChunks = bodyChunks || [];
36
- bodyChunks.push(chunk.subarray(offset, offset + length));
37
- };
38
- const readable = concatReadable(Readable.from(iterable), Readable.from(CRLF));
39
- msg.once('finish', () => {
40
- parser.finish();
41
- msg.complete = true;
42
- if (bodyChunks)
43
- msg.body = Buffer.concat(bodyChunks);
44
- });
45
- readable.pipe(msg);
46
- return msg;
47
- }
48
- NodeIncomingMessage.from = from;
49
- /**
50
- * Creates a new NodeIncomingMessage from given argument
51
- * @param iterable
52
- */
53
- async function fromAsync(iterable) {
54
- return new Promise((resolve, reject) => {
55
- const msg = from(iterable);
56
- msg.once('finish', () => resolve(msg));
57
- msg.once('error', error => reject(error));
58
- });
59
- }
60
- NodeIncomingMessage.fromAsync = fromAsync;
61
- })(NodeIncomingMessage || (NodeIncomingMessage = {}));
@@ -1,12 +0,0 @@
1
- import { NodeOutgoingMessageHost } from '../impl/node-outgoing-message.host.js';
2
- /**
3
- *
4
- * @namespace NodeOutgoingMessage
5
- */
6
- export var NodeOutgoingMessage;
7
- (function (NodeOutgoingMessage) {
8
- function from(init) {
9
- return new NodeOutgoingMessageHost(init);
10
- }
11
- NodeOutgoingMessage.from = from;
12
- })(NodeOutgoingMessage || (NodeOutgoingMessage = {}));
@@ -1,211 +0,0 @@
1
- import typeIs from '@browsery/type-is';
2
- import { BadRequestError, InternalServerError, OpraHttpError } from '@opra/common';
3
- import { Base64Decode } from 'base64-stream';
4
- import byteParser from 'bytes';
5
- import { parse as parseContentType } from 'content-type';
6
- import { EventEmitter } from 'events';
7
- import iconv from 'iconv-lite';
8
- import { Writable } from 'stream';
9
- import * as zlib from 'zlib';
10
- /**
11
- *
12
- * @class BodyReader
13
- */
14
- export class BodyReader extends EventEmitter {
15
- constructor(req, options) {
16
- super();
17
- this.req = req;
18
- this._completed = false;
19
- this._receivedSize = 0;
20
- this.onAborted = () => this._onAborted();
21
- this.onData = (chunk) => this._onData(chunk);
22
- this.onEnd = (err) => this._onEnd(err);
23
- this.cleanup = () => this._cleanup();
24
- this.limit = options?.limit
25
- ? typeof options.limit === 'number'
26
- ? options.limit
27
- : byteParser(options.limit)
28
- : undefined;
29
- }
30
- async read() {
31
- /* istanbul ignore next */
32
- if (this._completed) {
33
- throw new InternalServerError({
34
- message: 'Stream already read',
35
- code: 'STREAM_ALREADY_READ',
36
- });
37
- }
38
- if (!this.req.readable) {
39
- throw new InternalServerError({
40
- message: 'Stream is not readable',
41
- code: 'STREAM_NOT_READABLE',
42
- });
43
- }
44
- return new Promise((resolve, reject) => {
45
- // eslint-disable-next-line prefer-const
46
- let sizeStream;
47
- this.once('finish', (error, data) => {
48
- if (sizeStream)
49
- this.req.unpipe(sizeStream);
50
- if (error)
51
- return reject(error);
52
- resolve(data);
53
- });
54
- /**
55
- * Check if a request has a request body.
56
- * A request with a body __must__ either have `transfer-encoding`
57
- * or `content-length` headers set.
58
- * http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.3
59
- */
60
- const contentLength = parseInt(this.req.headers['content-length'] || '0', 10);
61
- if (this.req.headers['transfer-encoding'] === undefined && !(contentLength && !isNaN(contentLength))) {
62
- return this.onEnd();
63
- }
64
- // check the length and limit options.
65
- // note: we intentionally leave the stream paused,
66
- // so users should handle the stream themselves.
67
- if (this.limit != null && contentLength != null && contentLength > this.limit) {
68
- return this.onEnd(new OpraHttpError({
69
- message: 'Content Too Large',
70
- code: 'HTTP.CONTENT_TOO_LARGE',
71
- details: {
72
- length: contentLength,
73
- limit: this.limit,
74
- },
75
- }, 413));
76
- }
77
- // Pipe to a Writable stream to count received bytes
78
- const _this = this;
79
- sizeStream = new Writable({
80
- write(chunk, encoding, callback) {
81
- if (_this._completed)
82
- return;
83
- _this._receivedSize += chunk.length;
84
- if (_this.limit != null && _this._receivedSize > _this.limit) {
85
- callback(new OpraHttpError({
86
- message: 'Content Too Large',
87
- code: 'HTTP.CONTENT_TOO_LARGE',
88
- details: {
89
- limit: _this.limit,
90
- received: _this._receivedSize,
91
- },
92
- }, 413));
93
- }
94
- },
95
- });
96
- this.req.pipe(sizeStream);
97
- let stream = BodyReader.encoderPipeline(this.req);
98
- const mediaType = parseContentType(this.req.headers['content-type'] || '');
99
- let charset = (mediaType.parameters.charset || '').toLowerCase();
100
- if (!charset && typeIs.is(mediaType.type, ['json', 'xml', 'txt']))
101
- charset = 'utf-8';
102
- if (charset) {
103
- const newStream = iconv.decodeStream(charset);
104
- stream.pipe(newStream);
105
- stream = newStream;
106
- }
107
- this._stream = stream;
108
- // attach listeners
109
- stream.on('aborted', this.onAborted);
110
- stream.on('close', this.cleanup);
111
- stream.on('data', this.onData);
112
- stream.on('end', this.onEnd);
113
- stream.on('error', this.onEnd);
114
- });
115
- }
116
- _onEnd(error) {
117
- if (this._completed)
118
- return;
119
- this._completed = true;
120
- if (error) {
121
- this._stream?.unpipe();
122
- this._stream?.pause();
123
- }
124
- if (error)
125
- this.emit('finish', error);
126
- else if (Array.isArray(this._buffer))
127
- this.emit('finish', error, Buffer.concat(this._buffer));
128
- else
129
- this.emit('finish', error, this._buffer);
130
- this._cleanup();
131
- }
132
- _cleanup() {
133
- if (this._stream) {
134
- this._stream.removeListener('aborted', this.onAborted);
135
- this._stream.removeListener('close', this.cleanup);
136
- this._stream.removeListener('data', this.onData);
137
- this._stream.removeListener('end', this.onEnd);
138
- this._stream.removeListener('error', this.onEnd);
139
- }
140
- }
141
- _onAborted() {
142
- if (this._completed)
143
- return;
144
- this.onEnd(new BadRequestError({
145
- message: 'request aborted',
146
- code: 'ECONNABORTED',
147
- details: {
148
- received: this._receivedSize,
149
- },
150
- }));
151
- }
152
- _onData(chunk) {
153
- if (this._completed)
154
- return;
155
- if (typeof chunk === 'string') {
156
- this._buffer = this._buffer || '';
157
- this._buffer += chunk;
158
- }
159
- else {
160
- this._buffer = this._buffer || [];
161
- this._buffer.push(chunk);
162
- }
163
- }
164
- static async read(req, options) {
165
- const bodyReady = new BodyReader(req, options);
166
- return bodyReady.read();
167
- }
168
- static encoderPipeline(req) {
169
- const contentEncoding = req.headers['content-encoding'] || 'identity';
170
- const contentEncodings = (Array.isArray(contentEncoding) ? contentEncoding : contentEncoding.split(/\s*,\s*/))
171
- .map(s => s.toLowerCase())
172
- .reverse();
173
- return contentEncodings.reduce((prev, encoding) => {
174
- switch (encoding) {
175
- case 'gzip':
176
- case 'x-gzip': {
177
- const newStream = zlib.createGunzip();
178
- prev.pipe(newStream);
179
- return newStream;
180
- }
181
- case 'deflate':
182
- case 'x-deflate': {
183
- const newStream = zlib.createInflate();
184
- prev.pipe(newStream);
185
- return newStream;
186
- }
187
- case 'br': {
188
- const newStream = zlib.createBrotliDecompress();
189
- prev.pipe(newStream);
190
- return newStream;
191
- }
192
- case 'base64': {
193
- const newStream = new Base64Decode();
194
- prev.pipe(newStream);
195
- return newStream;
196
- }
197
- case 'identity':
198
- // prev.length = 0;
199
- return prev;
200
- default:
201
- throw new BadRequestError({
202
- message: 'unsupported content encoding "' + encoding + '"',
203
- code: '',
204
- details: {
205
- encoding,
206
- },
207
- }, 415);
208
- }
209
- }, req);
210
- }
211
- }
@@ -1,61 +0,0 @@
1
- /*
2
- This file contains code blocks from open source NodeJs project
3
- https://github.com/nodejs/
4
- */
5
- const tokenRegExp = /^[\^_`a-zA-Z\-0-9!#$%&'*+.|~]+$/;
6
- const nodeInternalPrefix = '__node_internal_';
7
- /**
8
- * Verifies that the given val is a valid HTTP token
9
- * per the rules defined in RFC 7230
10
- * See https://tools.ietf.org/html/rfc7230#section-3.2.6
11
- *
12
- * https://github.com/nodejs/node/blob/main/lib/_http_common.js
13
- */
14
- export function checkIsHttpToken(val) {
15
- return typeof val === 'string' && tokenRegExp.exec(val) !== null;
16
- }
17
- const headerCharRegex = /[^\t\x20-\x7e\x80-\xff]/;
18
- /**
19
- * True if val contains an invalid field-vchar
20
- * field-value = *( field-content / obs-fold )
21
- * field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
22
- * field-vchar = VCHAR / obs-text
23
- *
24
- * https://github.com/nodejs/node/blob/main/lib/_http_common.js
25
- */
26
- function checkInvalidHeaderChar(val) {
27
- // noinspection SuspiciousTypeOfGuard
28
- return typeof val === 'string' && headerCharRegex.exec(val) !== null;
29
- }
30
- /**
31
- * This function removes unnecessary frames from Node.js core errors.
32
- *
33
- * https://github.com/nodejs/node/blob/main/lib/internal/errors.js
34
- */
35
- export function hideStackFrames(fn) {
36
- // We rename the functions that will be hidden to cut off the stacktrace
37
- // at the outermost one
38
- const hidden = nodeInternalPrefix + fn.name;
39
- // @ts-ignore
40
- Object.defineProperty(fn, 'name', { __proto__: null, value: hidden });
41
- return fn;
42
- }
43
- export const validateHeaderName = hideStackFrames((name, label) => {
44
- // noinspection SuspiciousTypeOfGuard
45
- if (typeof name !== 'string' || !name || !checkIsHttpToken(name)) {
46
- throw new TypeError(`${label || 'Header name'} must be a valid HTTP token ["${name}"]`);
47
- }
48
- });
49
- export const validateHeaderValue = hideStackFrames((name, value) => {
50
- if (value === undefined) {
51
- throw new TypeError(`Invalid value "${value}" for header "${name}"`);
52
- }
53
- if (checkInvalidHeaderChar(value)) {
54
- throw new TypeError(`Invalid character in header content ["${name}"]`);
55
- }
56
- });
57
- export function validateString(value, name) {
58
- if (typeof value !== 'string') {
59
- throw new TypeError(`Invalid ${name ? name + ' ' : ''}argument. Value must be a string`);
60
- }
61
- }
@@ -1,16 +0,0 @@
1
- import { PassThrough } from 'stream';
2
- export function concatReadable(...streams) {
3
- const out = new PassThrough();
4
- const pipeNext = () => {
5
- const nextStream = streams.shift();
6
- if (nextStream) {
7
- nextStream.pipe(out, { end: false });
8
- nextStream.once('end', () => pipeNext());
9
- }
10
- else {
11
- out.end();
12
- }
13
- };
14
- pipeNext();
15
- return out;
16
- }
@@ -1,60 +0,0 @@
1
- import { ARRAY_FIELD, COMMA_DELIMITED_FIELD, matchKnownFields, SEMICOLON_DELIMITED_FIELD, } from './match-known-fields.js';
2
- export function convertToHeaders(src, dst, joinDuplicateHeaders) {
3
- for (let n = 0; n < src.length; n += 2) {
4
- addHeaderLine(src[n], src[n + 1], dst, joinDuplicateHeaders);
5
- }
6
- return dst;
7
- }
8
- export function convertToHeadersDistinct(src, dst) {
9
- const count = src.length % 2;
10
- for (let n = 0; n < count; n += 2) {
11
- addHeaderLineDistinct(src[n], src[n + 1], dst);
12
- }
13
- return dst;
14
- }
15
- function addHeaderLine(field, value, dest, joinDuplicateHeaders) {
16
- if (value == null)
17
- return;
18
- field = field.toLowerCase();
19
- const [, flag] = matchKnownFields(field);
20
- // comma(0) or semicolon(2) delimited field
21
- if (flag === COMMA_DELIMITED_FIELD || flag === SEMICOLON_DELIMITED_FIELD) {
22
- // Make a delimited list
23
- if (typeof dest[field] === 'string') {
24
- dest[field] += (flag === COMMA_DELIMITED_FIELD ? ', ' : '; ') + value;
25
- }
26
- else {
27
- dest[field] = value;
28
- }
29
- }
30
- else if (flag === ARRAY_FIELD) {
31
- // Array header -- only Set-Cookie at the moment
32
- if (dest['set-cookie'] !== undefined) {
33
- dest['set-cookie'].push(value);
34
- }
35
- else {
36
- dest['set-cookie'] = [value];
37
- }
38
- }
39
- else if (joinDuplicateHeaders) {
40
- if (dest[field] === undefined) {
41
- dest[field] = value;
42
- }
43
- else {
44
- dest[field] += ', ' + value;
45
- }
46
- }
47
- else if (dest[field] === undefined) {
48
- // Drop duplicates
49
- dest[field] = value;
50
- }
51
- }
52
- function addHeaderLineDistinct(field, value, dest) {
53
- field = field.toLowerCase();
54
- if (!dest[field]) {
55
- dest[field] = [value];
56
- }
57
- else {
58
- dest[field].push(value);
59
- }
60
- }
@@ -1,20 +0,0 @@
1
- import { ARRAY_FIELD, COMMA_DELIMITED_FIELD, matchKnownFields, SEMICOLON_DELIMITED_FIELD, } from './match-known-fields.js';
2
- export function convertToRawHeaders(src) {
3
- return Object.entries(src).reduce((a, [field, v]) => {
4
- const [name, flag] = matchKnownFields(field);
5
- if (flag === ARRAY_FIELD) {
6
- if (Array.isArray(v))
7
- v.forEach(x => a.push(name, String(x)));
8
- else
9
- a.push(name, String(v));
10
- return a;
11
- }
12
- if (flag === COMMA_DELIMITED_FIELD || flag === SEMICOLON_DELIMITED_FIELD) {
13
- v = Array.isArray(v) ? v.join(flag === COMMA_DELIMITED_FIELD ? ', ' : '; ') : String(v);
14
- }
15
- else
16
- v = Array.isArray(v) ? String(v[0]) : String(v);
17
- a.push(name, v);
18
- return a;
19
- }, []);
20
- }