@opra/core 0.20.3 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/adapter/adapter.js +2 -2
- package/cjs/adapter/http/express-adapter.js +29 -7
- package/cjs/adapter/http/helpers/common.js +66 -0
- package/cjs/adapter/http/helpers/convert-to-headers.js +65 -0
- package/cjs/adapter/http/helpers/convert-to-raw-headers.js +25 -0
- package/cjs/adapter/http/helpers/match-known-fields.js +47 -0
- package/cjs/adapter/http/http-adapter.js +76 -438
- package/cjs/adapter/http/impl/http-incoming-message-host.js +127 -0
- package/cjs/adapter/http/impl/http-outgoing-message-host.js +210 -0
- package/cjs/adapter/http/impl/http-server-request.js +125 -0
- package/cjs/adapter/http/impl/http-server-response.js +226 -0
- package/cjs/adapter/http/request-parsers/batch-request-parser.js +169 -0
- package/cjs/adapter/http/request-parsers/parse-collection-request.js +165 -0
- package/cjs/adapter/http/request-parsers/parse-request.js +24 -0
- package/cjs/adapter/http/request-parsers/parse-singleton-request.js +96 -0
- package/cjs/adapter/request-context.host.js +17 -3
- package/cjs/adapter/request.host.js +6 -3
- package/cjs/adapter/response.host.js +5 -3
- package/cjs/index.js +4 -2
- package/esm/adapter/adapter.js +2 -2
- package/esm/adapter/http/express-adapter.js +6 -6
- package/esm/adapter/http/helpers/common.js +60 -0
- package/esm/adapter/http/helpers/convert-to-headers.js +60 -0
- package/esm/adapter/http/helpers/convert-to-raw-headers.js +21 -0
- package/esm/adapter/http/helpers/match-known-fields.js +43 -0
- package/esm/adapter/http/http-adapter.js +77 -439
- package/esm/adapter/http/impl/http-incoming-message-host.js +122 -0
- package/esm/adapter/http/impl/http-outgoing-message-host.js +205 -0
- package/esm/adapter/http/impl/http-server-request.js +121 -0
- package/esm/adapter/http/impl/http-server-response.js +222 -0
- package/esm/adapter/http/request-parsers/batch-request-parser.js +169 -0
- package/esm/adapter/http/request-parsers/parse-collection-request.js +161 -0
- package/esm/adapter/http/request-parsers/parse-request.js +20 -0
- package/esm/adapter/http/request-parsers/parse-singleton-request.js +92 -0
- package/esm/adapter/request-context.host.js +17 -3
- package/esm/adapter/request.host.js +6 -3
- package/esm/adapter/response.host.js +5 -3
- package/esm/index.js +4 -2
- package/package.json +20 -16
- package/types/adapter/adapter.d.ts +1 -1
- package/types/adapter/http/helpers/common.d.ts +17 -0
- package/types/adapter/http/helpers/convert-to-headers.d.ts +2 -0
- package/types/adapter/http/helpers/convert-to-raw-headers.d.ts +3 -0
- package/types/adapter/http/helpers/match-known-fields.d.ts +6 -0
- package/types/adapter/http/http-adapter.d.ts +7 -12
- package/types/adapter/http/impl/http-incoming-message-host.d.ts +58 -0
- package/types/adapter/http/impl/http-outgoing-message-host.d.ts +72 -0
- package/types/adapter/http/{http-request-message.d.ts → impl/http-server-request.d.ts} +52 -85
- package/types/adapter/http/impl/http-server-response.d.ts +137 -0
- package/types/adapter/http/request-parsers/batch-request-parser.d.ts +0 -0
- package/types/adapter/http/request-parsers/parse-collection-request.d.ts +4 -0
- package/types/adapter/http/request-parsers/parse-request.d.ts +4 -0
- package/types/adapter/http/request-parsers/parse-singleton-request.d.ts +4 -0
- package/types/adapter/interfaces/request-context.interface.d.ts +14 -10
- package/types/adapter/interfaces/request.interface.d.ts +3 -2
- package/types/adapter/interfaces/response.interface.d.ts +2 -2
- package/types/adapter/request-context.host.d.ts +9 -6
- package/types/adapter/request.host.d.ts +8 -4
- package/types/adapter/response.host.d.ts +6 -4
- package/types/index.d.ts +4 -2
- package/cjs/adapter/http/http-message.host.js +0 -251
- package/cjs/adapter/http/http-request-context.host.js +0 -28
- package/cjs/adapter/http/http-request-message.js +0 -152
- package/cjs/adapter/http/http-request.host.js +0 -14
- package/cjs/adapter/http/http-response-message.js +0 -238
- package/cjs/adapter/http/http-response.host.js +0 -14
- package/esm/adapter/http/http-message.host.js +0 -246
- package/esm/adapter/http/http-request-context.host.js +0 -24
- package/esm/adapter/http/http-request-message.js +0 -148
- package/esm/adapter/http/http-request.host.js +0 -10
- package/esm/adapter/http/http-response-message.js +0 -233
- package/esm/adapter/http/http-response.host.js +0 -10
- package/types/adapter/http/http-message.host.d.ts +0 -122
- package/types/adapter/http/http-request-context.host.d.ts +0 -16
- package/types/adapter/http/http-request.host.d.ts +0 -7
- package/types/adapter/http/http-response-message.d.ts +0 -321
- package/types/adapter/http/http-response.host.d.ts +0 -7
|
@@ -1,238 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.HttpResponseMessageHost = exports.HttpResponseMessage = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const content_disposition_1 = tslib_1.__importDefault(require("content-disposition"));
|
|
6
|
-
const cookie_1 = tslib_1.__importDefault(require("cookie"));
|
|
7
|
-
const cookie_signature_1 = tslib_1.__importDefault(require("cookie-signature"));
|
|
8
|
-
const encodeurl_1 = tslib_1.__importDefault(require("encodeurl"));
|
|
9
|
-
const mime_types_1 = tslib_1.__importDefault(require("mime-types"));
|
|
10
|
-
const path_1 = tslib_1.__importDefault(require("path"));
|
|
11
|
-
const http_parser_1 = require("@browsery/http-parser");
|
|
12
|
-
const common_1 = require("@opra/common");
|
|
13
|
-
const http_message_host_js_1 = require("./http-message.host.js");
|
|
14
|
-
/**
|
|
15
|
-
* @namespace HttpResponseMessage
|
|
16
|
-
*/
|
|
17
|
-
var HttpResponseMessage;
|
|
18
|
-
(function (HttpResponseMessage) {
|
|
19
|
-
function create(init) {
|
|
20
|
-
return HttpResponseMessageHost.create(init);
|
|
21
|
-
}
|
|
22
|
-
HttpResponseMessage.create = create;
|
|
23
|
-
function fromBuffer(buffer) {
|
|
24
|
-
return HttpResponseMessageHost.fromBuffer(buffer);
|
|
25
|
-
}
|
|
26
|
-
HttpResponseMessage.fromBuffer = fromBuffer;
|
|
27
|
-
async function fromStream(readable) {
|
|
28
|
-
return HttpResponseMessageHost.fromStream(readable);
|
|
29
|
-
}
|
|
30
|
-
HttpResponseMessage.fromStream = fromStream;
|
|
31
|
-
})(HttpResponseMessage || (exports.HttpResponseMessage = HttpResponseMessage = {}));
|
|
32
|
-
/**
|
|
33
|
-
* @class HttpResponseMessageHost
|
|
34
|
-
*/
|
|
35
|
-
class HttpResponseMessageHost extends http_message_host_js_1.HttpMessageHost {
|
|
36
|
-
constructor() {
|
|
37
|
-
super();
|
|
38
|
-
}
|
|
39
|
-
header(arg0, arg1) {
|
|
40
|
-
return this.set(arg0, arg1);
|
|
41
|
-
}
|
|
42
|
-
append(name, value) {
|
|
43
|
-
this[http_message_host_js_1.HttpMessageHost.kHeaders].append(name, value);
|
|
44
|
-
return this;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Set "Content-Disposition" header to "attachment" with optional `filename`.
|
|
48
|
-
*/
|
|
49
|
-
attachment(filename) {
|
|
50
|
-
if (filename)
|
|
51
|
-
this.type(path_1.default.extname(filename));
|
|
52
|
-
this.set('Content-Disposition', (0, content_disposition_1.default)(filename));
|
|
53
|
-
return this;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Alias for msg.type()
|
|
57
|
-
*/
|
|
58
|
-
contentType(type) {
|
|
59
|
-
return this.type(type);
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Set _Content-Type_ response header with `type` through `mime.lookup()`
|
|
63
|
-
* when it does not contain "/", or set the Content-Type to `type` otherwise.
|
|
64
|
-
*
|
|
65
|
-
* Examples:
|
|
66
|
-
*
|
|
67
|
-
* res.type('.html');
|
|
68
|
-
* res.type('html');
|
|
69
|
-
* res.type('json');
|
|
70
|
-
* res.type('application/json');
|
|
71
|
-
* res.type('png');
|
|
72
|
-
*/
|
|
73
|
-
type(type) {
|
|
74
|
-
const ct = type.indexOf('/') === -1
|
|
75
|
-
? mime_types_1.default.lookup(type)
|
|
76
|
-
: type;
|
|
77
|
-
if (ct)
|
|
78
|
-
this.set('Content-Type', ct);
|
|
79
|
-
return this;
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Set cookie `name` to `value`, with the given `options`.
|
|
83
|
-
*
|
|
84
|
-
* Options:
|
|
85
|
-
*
|
|
86
|
-
* - `maxAge` max-age in milliseconds, converted to `expires`
|
|
87
|
-
* - `signed` sign the cookie
|
|
88
|
-
* - `path` defaults to "/"
|
|
89
|
-
*
|
|
90
|
-
* Examples:
|
|
91
|
-
*
|
|
92
|
-
* // "Remember Me" for 15 minutes
|
|
93
|
-
* res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });
|
|
94
|
-
*
|
|
95
|
-
* // same as above
|
|
96
|
-
* res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true })
|
|
97
|
-
*
|
|
98
|
-
*/
|
|
99
|
-
cookie(name, value, options) {
|
|
100
|
-
const opts = { ...options };
|
|
101
|
-
const secret = this.req?.secret;
|
|
102
|
-
const signed = opts.signed;
|
|
103
|
-
if (signed && !secret) {
|
|
104
|
-
throw new Error('cookieParser("secret") required for signed cookies');
|
|
105
|
-
}
|
|
106
|
-
let val = typeof value === 'object'
|
|
107
|
-
? 'j:' + JSON.stringify(value)
|
|
108
|
-
: String(value);
|
|
109
|
-
if (signed)
|
|
110
|
-
val = 's:' + cookie_signature_1.default.sign(val, secret);
|
|
111
|
-
if (opts.maxAge != null) {
|
|
112
|
-
const maxAge = opts.maxAge - 0;
|
|
113
|
-
if (!isNaN(maxAge)) {
|
|
114
|
-
opts.expires = new Date(Date.now() + maxAge);
|
|
115
|
-
opts.maxAge = Math.floor(maxAge / 1000);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
if (opts.path == null)
|
|
119
|
-
opts.path = '/';
|
|
120
|
-
// Remove old cookie
|
|
121
|
-
let a = this.get('Set-Cookie');
|
|
122
|
-
if (a && Array.isArray(a)) {
|
|
123
|
-
a = a.filter(x => !x.startsWith(name + '='));
|
|
124
|
-
this.set('Set-Cookie', a);
|
|
125
|
-
}
|
|
126
|
-
this.append('Set-Cookie', cookie_1.default.serialize(name, String(val), opts));
|
|
127
|
-
return this;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Clear cookie `name`.
|
|
131
|
-
*/
|
|
132
|
-
clearCookie(name, options) {
|
|
133
|
-
return this.cookie(name, '', { expires: new Date(1), path: '/', ...options });
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Set Link header field with the given `links`.
|
|
137
|
-
*
|
|
138
|
-
* Examples:
|
|
139
|
-
*
|
|
140
|
-
* res.links({
|
|
141
|
-
* next: 'http://api.example.com/users?page=2',
|
|
142
|
-
* last: 'http://api.example.com/users?page=5'
|
|
143
|
-
* });
|
|
144
|
-
*
|
|
145
|
-
*/
|
|
146
|
-
links(links) {
|
|
147
|
-
let link = this.get('Link') || '';
|
|
148
|
-
if (link)
|
|
149
|
-
link += ', ';
|
|
150
|
-
return this.set('Link', link + Object.keys(links).map(rel => '<' + links[rel] + '>; rel="' + rel + '"').join(', '));
|
|
151
|
-
}
|
|
152
|
-
redirect(arg0, url) {
|
|
153
|
-
let status = 302;
|
|
154
|
-
// allow status / url
|
|
155
|
-
if (typeof arg0 === 'number') {
|
|
156
|
-
status = arg0;
|
|
157
|
-
}
|
|
158
|
-
else
|
|
159
|
-
url = arg0 || '';
|
|
160
|
-
// Set location header
|
|
161
|
-
this.location(url || '/');
|
|
162
|
-
// Respond
|
|
163
|
-
this.statusCode = status;
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Send JSON response.
|
|
167
|
-
*
|
|
168
|
-
* Examples:
|
|
169
|
-
*
|
|
170
|
-
* res.json(null);
|
|
171
|
-
* res.json({ user: 'tj' });
|
|
172
|
-
*/
|
|
173
|
-
json(obj) {
|
|
174
|
-
if (!this.get('Content-Type'))
|
|
175
|
-
this.set('Content-Type', 'application/json');
|
|
176
|
-
const body = JSON.stringify(obj);
|
|
177
|
-
return this.send(body);
|
|
178
|
-
}
|
|
179
|
-
location(url) {
|
|
180
|
-
let loc = url;
|
|
181
|
-
// "back" is an alias for the referrer
|
|
182
|
-
if (url === 'back')
|
|
183
|
-
loc = this.req?.get('Referrer') || '/';
|
|
184
|
-
// set location
|
|
185
|
-
return this.set('Location', (0, encodeurl_1.default)(loc));
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* Set status `code`.
|
|
189
|
-
*/
|
|
190
|
-
status(code) {
|
|
191
|
-
this.statusCode = code;
|
|
192
|
-
return this;
|
|
193
|
-
}
|
|
194
|
-
/**
|
|
195
|
-
* Set the response HTTP status code to `statusCode` and send its string representation as the response body.
|
|
196
|
-
* @link http://expressjs.com/4x/api.html#res.sendStatus
|
|
197
|
-
*
|
|
198
|
-
* Examples:
|
|
199
|
-
*
|
|
200
|
-
* res.sendStatus(200); // equivalent to res.status(200).send('OK')
|
|
201
|
-
* res.sendStatus(403); // equivalent to res.status(403).send('Forbidden')
|
|
202
|
-
* res.sendStatus(404); // equivalent to res.status(404).send('Not Found')
|
|
203
|
-
* res.sendStatus(500); // equivalent to res.status(500).send('Internal Server Error')
|
|
204
|
-
*/
|
|
205
|
-
sendStatus(statusCode) {
|
|
206
|
-
const body = common_1.HttpStatusMessages[statusCode] || String(statusCode);
|
|
207
|
-
this.statusCode = statusCode;
|
|
208
|
-
this.type('txt');
|
|
209
|
-
return this.send(body);
|
|
210
|
-
}
|
|
211
|
-
_init(init) {
|
|
212
|
-
super._init(init);
|
|
213
|
-
this.statusCode = init?.statusCode;
|
|
214
|
-
this.statusMessage = init?.statusMessage;
|
|
215
|
-
this.req = init?.req;
|
|
216
|
-
this.chunkedEncoding = init?.chunkedEncoding;
|
|
217
|
-
}
|
|
218
|
-
[http_message_host_js_1.HttpMessageHost.kOnHeaderReceived](info) {
|
|
219
|
-
super[http_message_host_js_1.HttpMessageHost.kOnHeaderReceived](info);
|
|
220
|
-
this.statusCode = info.statusCode;
|
|
221
|
-
this.statusMessage = info.statusMessage;
|
|
222
|
-
}
|
|
223
|
-
static create(init) {
|
|
224
|
-
const msg = new HttpResponseMessageHost();
|
|
225
|
-
msg._init(init);
|
|
226
|
-
return msg;
|
|
227
|
-
}
|
|
228
|
-
static fromBuffer(buffer) {
|
|
229
|
-
const msg = new HttpResponseMessageHost();
|
|
230
|
-
msg._parseBuffer(buffer, http_parser_1.HTTPParser.RESPONSE);
|
|
231
|
-
return msg;
|
|
232
|
-
}
|
|
233
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
234
|
-
static async fromStream(readable) {
|
|
235
|
-
throw new Error('fromStream is not implemented yet');
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
exports.HttpResponseMessageHost = HttpResponseMessageHost;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.HttpResponseHost = void 0;
|
|
4
|
-
const response_host_js_1 = require("../response.host.js");
|
|
5
|
-
class HttpResponseHost extends response_host_js_1.ResponseHost {
|
|
6
|
-
constructor(init, _outgoing) {
|
|
7
|
-
super(init);
|
|
8
|
-
this._outgoing = _outgoing;
|
|
9
|
-
}
|
|
10
|
-
switchToHttp() {
|
|
11
|
-
return this._outgoing;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
exports.HttpResponseHost = HttpResponseHost;
|
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
import * as stream from 'stream';
|
|
2
|
-
import { HTTPParser } from '@browsery/http-parser';
|
|
3
|
-
import { HttpHeaders } from '@opra/common';
|
|
4
|
-
const kHeaders = Symbol('kHeaders');
|
|
5
|
-
const kHeadersProxy = Symbol('kHeadersProxy');
|
|
6
|
-
const kTrailers = Symbol('kTrailers');
|
|
7
|
-
const kTrailersProxy = Symbol('kTrailersProxy');
|
|
8
|
-
const kOnHeaderReceived = Symbol('kOnHeaderReceived');
|
|
9
|
-
const kOnTrailersReceived = Symbol('kOnTrailersReceived');
|
|
10
|
-
const kOnBodyChunk = Symbol('kOnBodyChunk');
|
|
11
|
-
const kOnReadComplete = Symbol('kOnReadComplete');
|
|
12
|
-
const crlfBuffer = Buffer.from('\r\n');
|
|
13
|
-
const HTTP_VERSION_PATTERN = /^(\d)\.(\d)$/;
|
|
14
|
-
export class HttpMessageHost {
|
|
15
|
-
constructor() {
|
|
16
|
-
this.complete = false;
|
|
17
|
-
stream.Duplex.apply(this);
|
|
18
|
-
this[kHeaders] = new HttpHeaders(undefined, {
|
|
19
|
-
onChange: () => this._headersChanged = true
|
|
20
|
-
});
|
|
21
|
-
this[kTrailers] = new HttpHeaders(undefined, {
|
|
22
|
-
onChange: () => this._trailersChanged = true
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
get httpVersion() {
|
|
26
|
-
return this.httpVersionMajor
|
|
27
|
-
? this.httpVersionMajor + '.' + (this.httpVersionMinor || 0)
|
|
28
|
-
: undefined;
|
|
29
|
-
}
|
|
30
|
-
set httpVersion(value) {
|
|
31
|
-
if (value) {
|
|
32
|
-
const m = HTTP_VERSION_PATTERN.exec(value);
|
|
33
|
-
if (!m)
|
|
34
|
-
throw new TypeError(`Invalid http version string (${value})`);
|
|
35
|
-
this.httpVersionMajor = parseInt(m[1], 10);
|
|
36
|
-
this.httpVersionMinor = parseInt(m[2], 10);
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
this.httpVersionMajor = undefined;
|
|
40
|
-
this.httpVersionMinor = undefined;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
get headers() {
|
|
44
|
-
this._initHeaders();
|
|
45
|
-
return this[kHeadersProxy];
|
|
46
|
-
}
|
|
47
|
-
set headers(headers) {
|
|
48
|
-
this[kHeaders].clear();
|
|
49
|
-
this[kHeaders].set(headers);
|
|
50
|
-
}
|
|
51
|
-
get trailers() {
|
|
52
|
-
this._initTrailers();
|
|
53
|
-
return this[kTrailersProxy];
|
|
54
|
-
}
|
|
55
|
-
set trailers(trailers) {
|
|
56
|
-
this[kTrailers].clear();
|
|
57
|
-
this[kTrailers].set(trailers);
|
|
58
|
-
}
|
|
59
|
-
get rawHeaders() {
|
|
60
|
-
this._buildRawHeaders();
|
|
61
|
-
return this._rawHeaders;
|
|
62
|
-
}
|
|
63
|
-
set rawHeaders(headers) {
|
|
64
|
-
this[kHeadersProxy] = undefined;
|
|
65
|
-
this._headersChanged = false;
|
|
66
|
-
this._rawHeaders = headers;
|
|
67
|
-
}
|
|
68
|
-
get rawTrailers() {
|
|
69
|
-
this._buildRawTrailers();
|
|
70
|
-
return this._rawTrailers;
|
|
71
|
-
}
|
|
72
|
-
set rawTrailers(trailers) {
|
|
73
|
-
this[kTrailersProxy] = undefined;
|
|
74
|
-
this._trailersChanged = false;
|
|
75
|
-
this._rawTrailers = trailers;
|
|
76
|
-
}
|
|
77
|
-
getHeader(name) {
|
|
78
|
-
if (!name)
|
|
79
|
-
return;
|
|
80
|
-
this._initHeaders();
|
|
81
|
-
switch (name.toLowerCase()) {
|
|
82
|
-
case 'referer':
|
|
83
|
-
case 'referrer':
|
|
84
|
-
return this[kHeaders].get(name) ||
|
|
85
|
-
this[kHeaders].get('referrer') ||
|
|
86
|
-
this[kHeaders].get('referer');
|
|
87
|
-
default:
|
|
88
|
-
return this[kHeaders].get(name);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
get(name) {
|
|
92
|
-
this._initHeaders();
|
|
93
|
-
return this[kHeaders].get(name);
|
|
94
|
-
}
|
|
95
|
-
setHeader(arg0, arg1) {
|
|
96
|
-
this._initHeaders();
|
|
97
|
-
if (typeof arg0 === 'object')
|
|
98
|
-
this[kHeaders].set(arg0);
|
|
99
|
-
else
|
|
100
|
-
this[kHeaders].set(arg0, arg1);
|
|
101
|
-
return this;
|
|
102
|
-
}
|
|
103
|
-
set(arg0, arg1) {
|
|
104
|
-
return this.setHeader(arg0, arg1);
|
|
105
|
-
}
|
|
106
|
-
getHeaders() {
|
|
107
|
-
this._initHeaders();
|
|
108
|
-
return this[kHeaders].toObject();
|
|
109
|
-
}
|
|
110
|
-
getHeaderNames() {
|
|
111
|
-
this._initHeaders();
|
|
112
|
-
return Array.from(this[kHeaders].keys());
|
|
113
|
-
}
|
|
114
|
-
hasHeader(name) {
|
|
115
|
-
this._initHeaders();
|
|
116
|
-
return this[kHeaders].has(name);
|
|
117
|
-
}
|
|
118
|
-
removeHeader(name) {
|
|
119
|
-
this._initHeaders();
|
|
120
|
-
this[kHeaders].delete(name);
|
|
121
|
-
}
|
|
122
|
-
send(body) {
|
|
123
|
-
this.body = body;
|
|
124
|
-
return this;
|
|
125
|
-
}
|
|
126
|
-
end(body) {
|
|
127
|
-
if (body)
|
|
128
|
-
this.body = body;
|
|
129
|
-
return this;
|
|
130
|
-
}
|
|
131
|
-
setTimeout() {
|
|
132
|
-
return this;
|
|
133
|
-
}
|
|
134
|
-
_init(args) {
|
|
135
|
-
this.complete = true;
|
|
136
|
-
this.httpVersionMajor = args?.httpVersionMajor;
|
|
137
|
-
this.httpVersionMinor = args?.httpVersionMinor;
|
|
138
|
-
this._rawHeaders = args.rawHeaders;
|
|
139
|
-
this._rawTrailers = args.rawTrailers;
|
|
140
|
-
if (args.headers)
|
|
141
|
-
this[kHeaders].set(args.headers);
|
|
142
|
-
if (args.trailers)
|
|
143
|
-
this[kTrailers].set(args.trailers);
|
|
144
|
-
this.body = args.body;
|
|
145
|
-
}
|
|
146
|
-
_parseBuffer(buf, parserType) {
|
|
147
|
-
const parser = new HTTPParser(parserType);
|
|
148
|
-
parser[HTTPParser.kOnHeadersComplete] = this[kOnHeaderReceived].bind(this);
|
|
149
|
-
parser[HTTPParser.kOnBody] = this[kOnBodyChunk].bind(this);
|
|
150
|
-
parser[HTTPParser.kOnHeaders] = this[kOnTrailersReceived].bind(this);
|
|
151
|
-
parser[HTTPParser.kOnMessageComplete] = this[kOnReadComplete].bind(this);
|
|
152
|
-
const buffer = Buffer.from(buf);
|
|
153
|
-
let x = parser.execute(buffer);
|
|
154
|
-
if (typeof x === 'object')
|
|
155
|
-
throw x;
|
|
156
|
-
if (!this.complete) {
|
|
157
|
-
x = parser.execute(crlfBuffer);
|
|
158
|
-
if (typeof x === 'object')
|
|
159
|
-
throw x;
|
|
160
|
-
}
|
|
161
|
-
parser.finish();
|
|
162
|
-
}
|
|
163
|
-
_initHeaders() {
|
|
164
|
-
if (!this[kHeadersProxy]) {
|
|
165
|
-
this[kHeadersProxy] = this[kHeaders].getProxy();
|
|
166
|
-
if (this._rawHeaders) {
|
|
167
|
-
const src = this._rawHeaders;
|
|
168
|
-
const l = Math.floor(src.length / 2);
|
|
169
|
-
for (let n = 0; n <= l; n += 2) {
|
|
170
|
-
this[kHeaders].append(src[n], src[n + 1]);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
_initTrailers() {
|
|
176
|
-
if (!this[kTrailersProxy]) {
|
|
177
|
-
this[kTrailersProxy] = this[kTrailers].getProxy();
|
|
178
|
-
if (this._rawTrailers) {
|
|
179
|
-
const src = this._rawTrailers;
|
|
180
|
-
const l = Math.floor(src.length / 2);
|
|
181
|
-
for (let n = 0; n <= l; n += 2) {
|
|
182
|
-
this[kTrailers].append(src[n], src[n + 1]);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
_buildRawHeaders() {
|
|
188
|
-
// Rebuild rawHeaders if headers object changed
|
|
189
|
-
if (this._headersChanged || !this._rawHeaders) {
|
|
190
|
-
this._headersChanged = false;
|
|
191
|
-
this._rawHeaders = Object.entries(this.headers)
|
|
192
|
-
.reduce((a, [k, v]) => {
|
|
193
|
-
if (Array.isArray(v))
|
|
194
|
-
v.forEach(x => a.push(k, String(x)));
|
|
195
|
-
else
|
|
196
|
-
a.push(k, String(v));
|
|
197
|
-
return a;
|
|
198
|
-
}, []);
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
_buildRawTrailers() {
|
|
202
|
-
// Rebuild rawHeaders if headers object changed
|
|
203
|
-
if (this._trailersChanged || !this._rawTrailers) {
|
|
204
|
-
this._trailersChanged = false;
|
|
205
|
-
this._rawTrailers = Object.entries(this.trailers)
|
|
206
|
-
.reduce((a, [k, v]) => {
|
|
207
|
-
if (Array.isArray(v))
|
|
208
|
-
v.forEach(x => a.push(k, String(x)));
|
|
209
|
-
else
|
|
210
|
-
a.push(k, String(v));
|
|
211
|
-
return a;
|
|
212
|
-
}, []);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
[kOnHeaderReceived](info) {
|
|
216
|
-
this.httpVersionMajor = info.versionMajor;
|
|
217
|
-
this.httpVersionMinor = info.versionMinor;
|
|
218
|
-
this._rawHeaders = info.headers;
|
|
219
|
-
this.shouldKeepAlive = info.shouldKeepAlive;
|
|
220
|
-
this.upgrade = info.upgrade;
|
|
221
|
-
}
|
|
222
|
-
[kOnTrailersReceived](trailers) {
|
|
223
|
-
this._rawTrailers = trailers;
|
|
224
|
-
}
|
|
225
|
-
[kOnBodyChunk](chunk, offset, length) {
|
|
226
|
-
this._bodyChunks = this._bodyChunks || [];
|
|
227
|
-
this._bodyChunks.push(chunk.subarray(offset, offset + length));
|
|
228
|
-
}
|
|
229
|
-
[kOnReadComplete]() {
|
|
230
|
-
this.complete = true;
|
|
231
|
-
if (this._bodyChunks) {
|
|
232
|
-
this.body = Buffer.concat(this._bodyChunks);
|
|
233
|
-
this._bodyChunks = undefined;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
HttpMessageHost.kHeaders = kHeaders;
|
|
238
|
-
HttpMessageHost.kHeadersProxy = kHeadersProxy;
|
|
239
|
-
HttpMessageHost.kTrailers = kTrailers;
|
|
240
|
-
HttpMessageHost.kTrailersProxy = kTrailersProxy;
|
|
241
|
-
HttpMessageHost.kOnHeaderReceived = kOnHeaderReceived;
|
|
242
|
-
HttpMessageHost.kOnTrailersReceived = kOnTrailersReceived;
|
|
243
|
-
HttpMessageHost.kOnBodyChunk = kOnBodyChunk;
|
|
244
|
-
HttpMessageHost.kOnReadComplete = kOnReadComplete;
|
|
245
|
-
// Mixin with Duplex
|
|
246
|
-
Object.assign(HttpMessageHost.prototype, stream.Duplex.prototype);
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { RequestContextHost } from '../request-context.host.js';
|
|
2
|
-
export class HttpRequestContextHost extends RequestContextHost {
|
|
3
|
-
constructor(platform, api, _request, _response) {
|
|
4
|
-
super('http', platform, api, _request, _response);
|
|
5
|
-
this.platform = platform;
|
|
6
|
-
this.api = api;
|
|
7
|
-
this._request = _request;
|
|
8
|
-
this._response = _response;
|
|
9
|
-
}
|
|
10
|
-
switchToHttp() {
|
|
11
|
-
const obj = {
|
|
12
|
-
request: this._request.switchToHttp(),
|
|
13
|
-
response: this._response.switchToHttp()
|
|
14
|
-
};
|
|
15
|
-
Object.setPrototypeOf(obj, this);
|
|
16
|
-
return obj;
|
|
17
|
-
}
|
|
18
|
-
switchToWs() {
|
|
19
|
-
throw new TypeError('Not executing in an "WebSocket" protocol');
|
|
20
|
-
}
|
|
21
|
-
switchToRpc() {
|
|
22
|
-
throw new TypeError('Not executing in an "RPC" protocol');
|
|
23
|
-
}
|
|
24
|
-
}
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import accepts from 'accepts';
|
|
2
|
-
import typeIs from 'type-is';
|
|
3
|
-
import { HTTPParser } from '@browsery/http-parser';
|
|
4
|
-
import { HttpParams } from '@opra/common';
|
|
5
|
-
import { HttpMessageHost } from './http-message.host.js';
|
|
6
|
-
const HTTP_VERSION_PATTERN = /^(\d)\.(\d)$/;
|
|
7
|
-
export var HttpRequestMessage;
|
|
8
|
-
(function (HttpRequestMessage) {
|
|
9
|
-
function create(init) {
|
|
10
|
-
return HttpRequestMessageHost.create(init);
|
|
11
|
-
}
|
|
12
|
-
HttpRequestMessage.create = create;
|
|
13
|
-
function fromBuffer(buffer) {
|
|
14
|
-
return HttpRequestMessageHost.fromBuffer(buffer);
|
|
15
|
-
}
|
|
16
|
-
HttpRequestMessage.fromBuffer = fromBuffer;
|
|
17
|
-
async function fromStream(readable) {
|
|
18
|
-
return HttpRequestMessageHost.fromStream(readable);
|
|
19
|
-
}
|
|
20
|
-
HttpRequestMessage.fromStream = fromStream;
|
|
21
|
-
})(HttpRequestMessage || (HttpRequestMessage = {}));
|
|
22
|
-
const kQuery = Symbol('kQuery');
|
|
23
|
-
const kQueryProxy = Symbol('kQueryProxy');
|
|
24
|
-
const kProtocol = Symbol('kProtocol');
|
|
25
|
-
/**
|
|
26
|
-
*
|
|
27
|
-
*/
|
|
28
|
-
class HttpRequestMessageHost extends HttpMessageHost {
|
|
29
|
-
constructor() {
|
|
30
|
-
super();
|
|
31
|
-
this.httpVersionMajor = 1;
|
|
32
|
-
this.httpVersionMinor = 0;
|
|
33
|
-
this[kQuery] = new HttpParams();
|
|
34
|
-
this[kQueryProxy] = this[kQuery].getProxy();
|
|
35
|
-
}
|
|
36
|
-
get httpVersion() {
|
|
37
|
-
return this.httpVersionMajor + '.' + this.httpVersionMinor;
|
|
38
|
-
}
|
|
39
|
-
set httpVersion(value) {
|
|
40
|
-
const m = HTTP_VERSION_PATTERN.exec(value);
|
|
41
|
-
if (!m)
|
|
42
|
-
throw new TypeError(`Invalid http version string (${value})`);
|
|
43
|
-
this.httpVersionMajor = parseInt(m[1], 10);
|
|
44
|
-
this.httpVersionMinor = parseInt(m[2], 10);
|
|
45
|
-
}
|
|
46
|
-
get hostname() {
|
|
47
|
-
let host = this.get('X-Forwarded-Host') || this.get('Host');
|
|
48
|
-
if (host && host.indexOf(',') !== -1) {
|
|
49
|
-
// Note: X-Forwarded-Host is normally only ever a single value, but this is to be safe.
|
|
50
|
-
host = host.substring(0, host.indexOf(',')).trimEnd();
|
|
51
|
-
}
|
|
52
|
-
if (!host)
|
|
53
|
-
return '';
|
|
54
|
-
// IPv6 literal support
|
|
55
|
-
const offset = host[0] === '['
|
|
56
|
-
? host.indexOf(']') + 1
|
|
57
|
-
: 0;
|
|
58
|
-
const index = host.indexOf(':', offset);
|
|
59
|
-
return index !== -1
|
|
60
|
-
? host.substring(0, index)
|
|
61
|
-
: host;
|
|
62
|
-
}
|
|
63
|
-
get protocol() {
|
|
64
|
-
if (this[kProtocol])
|
|
65
|
-
return this[kProtocol];
|
|
66
|
-
// Note: X-Forwarded-Proto is normally only ever a
|
|
67
|
-
// single value, but this is to be safe.
|
|
68
|
-
const header = this.get('X-Forwarded-Proto');
|
|
69
|
-
if (header) {
|
|
70
|
-
const index = header.indexOf(',');
|
|
71
|
-
return index !== -1
|
|
72
|
-
? header.substring(0, index).trim()
|
|
73
|
-
: header.trim();
|
|
74
|
-
}
|
|
75
|
-
return 'http';
|
|
76
|
-
}
|
|
77
|
-
set protocol(v) {
|
|
78
|
-
this[kProtocol] = v;
|
|
79
|
-
}
|
|
80
|
-
get secure() {
|
|
81
|
-
return this.protocol === 'https';
|
|
82
|
-
}
|
|
83
|
-
get query() {
|
|
84
|
-
return this[kQueryProxy];
|
|
85
|
-
}
|
|
86
|
-
set query(value) {
|
|
87
|
-
this[kQuery].clear();
|
|
88
|
-
this[kQuery].appendAll(value);
|
|
89
|
-
}
|
|
90
|
-
header(name) {
|
|
91
|
-
return this.getHeader(name);
|
|
92
|
-
}
|
|
93
|
-
accepts(...type) {
|
|
94
|
-
const accept = accepts(this);
|
|
95
|
-
// eslint-disable-next-line prefer-spread
|
|
96
|
-
return accept.types.apply(accept, type);
|
|
97
|
-
}
|
|
98
|
-
acceptsCharsets(...charset) {
|
|
99
|
-
const accept = accepts(this);
|
|
100
|
-
// eslint-disable-next-line prefer-spread
|
|
101
|
-
return accept.charsets.apply(accept, charset);
|
|
102
|
-
}
|
|
103
|
-
acceptsEncodings(...encoding) {
|
|
104
|
-
const accept = accepts(this);
|
|
105
|
-
// eslint-disable-next-line prefer-spread
|
|
106
|
-
return accept.encodings.apply(accept, encoding);
|
|
107
|
-
}
|
|
108
|
-
acceptsLanguages(...lang) {
|
|
109
|
-
const accept = accepts(this);
|
|
110
|
-
// eslint-disable-next-line prefer-spread
|
|
111
|
-
return accept.languages.apply(accept, lang);
|
|
112
|
-
}
|
|
113
|
-
is(type, ...otherTypes) {
|
|
114
|
-
const types = Array.isArray(type) ? type : [type];
|
|
115
|
-
if (otherTypes.length)
|
|
116
|
-
types.push(...otherTypes);
|
|
117
|
-
const contentType = this.getHeader('content-type');
|
|
118
|
-
return contentType ? typeIs.is(contentType, types) : null;
|
|
119
|
-
}
|
|
120
|
-
_init(init) {
|
|
121
|
-
super._init(init);
|
|
122
|
-
this.method = init.method.toUpperCase();
|
|
123
|
-
this.url = init.url;
|
|
124
|
-
this.baseUrl = init.baseUrl || this.url;
|
|
125
|
-
this.protocol = init.protocol;
|
|
126
|
-
}
|
|
127
|
-
[HttpMessageHost.kOnHeaderReceived](info) {
|
|
128
|
-
super[HttpMessageHost.kOnHeaderReceived](info);
|
|
129
|
-
this.method = HTTPParser.methods[info.method];
|
|
130
|
-
this.url = info.url;
|
|
131
|
-
this.baseUrl = info.url;
|
|
132
|
-
}
|
|
133
|
-
static create(init) {
|
|
134
|
-
const msg = new HttpRequestMessageHost();
|
|
135
|
-
msg._init(init);
|
|
136
|
-
return msg;
|
|
137
|
-
}
|
|
138
|
-
static fromBuffer(buffer) {
|
|
139
|
-
const msg = new HttpRequestMessageHost();
|
|
140
|
-
msg._parseBuffer(buffer, HTTPParser.REQUEST);
|
|
141
|
-
return msg;
|
|
142
|
-
}
|
|
143
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
144
|
-
static async fromStream(readable) {
|
|
145
|
-
throw new Error('fromStream is not implemented yet');
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
HttpRequestMessageHost.kQuery = kQuery;
|