@opra/common 0.10.2 → 0.12.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/filter/antlr/OpraFilterLexer.js +1 -1
- package/cjs/filter/antlr/OpraFilterListener.js +1 -1
- package/cjs/filter/antlr/OpraFilterParser.js +5 -5
- package/cjs/filter/antlr/OpraFilterVisitor.js +1 -1
- package/cjs/filter/filter-tree-visitor.js +8 -2
- package/cjs/filter/opra-error-listener.js +2 -2
- package/cjs/filter/parse.js +1 -1
- package/cjs/helpers/responsive-map.js +45 -28
- package/{esm/http/enums/http-headers.enum.js → cjs/http/enums/http-headers-codes.enum.js} +95 -92
- package/{esm/http/enums/http-status.enum.js → cjs/http/enums/http-status-codes.enum.js} +62 -59
- package/cjs/http/http-headers.js +213 -0
- package/cjs/http/http-param-codec.js +6 -0
- package/cjs/http/http-params.js +321 -0
- package/cjs/http/http-request-node.js +105 -0
- package/cjs/http/http-request.js +73 -88
- package/cjs/http/http-response.js +23 -0
- package/cjs/http/index.js +13 -2
- package/cjs/http/multipart/batch-multipart.js +12 -12
- package/cjs/http/param-codec/boolean-codec.js +25 -0
- package/cjs/http/param-codec/date-codec.js +44 -0
- package/cjs/http/param-codec/filter-codec.js +18 -0
- package/cjs/http/param-codec/integer-codec.js +19 -0
- package/cjs/http/param-codec/number-codec.js +26 -0
- package/cjs/http/param-codec/string-codec.js +25 -0
- package/cjs/http/utils/encodeURIParam.js +21 -0
- package/cjs/http/utils/normalize-headers.js +2 -2
- package/cjs/i18n/i18n.js +1 -4
- package/cjs/schema/implementation/opra-document.js +12 -11
- package/cjs/schema/implementation/resource/collection-resource-info.js +7 -0
- package/cjs/url/opra-url-path.js +96 -72
- package/cjs/url/opra-url-search-params.js +16 -234
- package/cjs/url/opra-url.js +201 -160
- package/esm/filter/antlr/OpraFilterLexer.d.ts +1 -1
- package/esm/filter/antlr/OpraFilterLexer.js +1 -1
- package/esm/filter/antlr/OpraFilterListener.d.ts +1 -1
- package/esm/filter/antlr/OpraFilterListener.js +1 -1
- package/esm/filter/antlr/OpraFilterParser.d.ts +1 -1
- package/esm/filter/antlr/OpraFilterParser.js +5 -5
- package/esm/filter/antlr/OpraFilterVisitor.d.ts +1 -1
- package/esm/filter/antlr/OpraFilterVisitor.js +1 -1
- package/esm/filter/ast/expressions/arithmetic-expression.d.ts +1 -1
- package/esm/filter/ast/expressions/comparison-expression.d.ts +1 -1
- package/esm/filter/ast/expressions/logical-expression.d.ts +1 -1
- package/esm/filter/build.d.ts +3 -3
- package/esm/filter/errors.d.ts +4 -2
- package/esm/filter/filter-tree-visitor.d.ts +2 -1
- package/esm/filter/filter-tree-visitor.js +8 -2
- package/esm/filter/opra-error-listener.d.ts +2 -2
- package/esm/filter/opra-error-listener.js +2 -2
- package/esm/filter/parse.d.ts +1 -1
- package/esm/filter/parse.js +1 -1
- package/esm/helpers/responsive-map.d.ts +19 -5
- package/esm/helpers/responsive-map.js +45 -28
- package/esm/http/enums/{http-headers.enum.d.ts → http-headers-codes.enum.d.ts} +1 -1
- package/{cjs/http/enums/http-headers.enum.js → esm/http/enums/http-headers-codes.enum.js} +92 -95
- package/esm/http/enums/{http-status.enum.d.ts → http-status-codes.enum.d.ts} +1 -1
- package/{cjs/http/enums/http-status.enum.js → esm/http/enums/http-status-codes.enum.js} +59 -62
- package/esm/http/http-headers.d.ts +70 -0
- package/esm/http/http-headers.js +209 -0
- package/esm/http/http-param-codec.d.ts +4 -0
- package/esm/http/http-param-codec.js +2 -0
- package/esm/http/http-params.d.ts +99 -0
- package/esm/http/http-params.js +317 -0
- package/esm/http/http-request-node.d.ts +34 -0
- package/esm/http/http-request-node.js +101 -0
- package/esm/http/http-request.d.ts +73 -31
- package/esm/http/http-request.js +72 -87
- package/esm/http/http-response.d.ts +41 -0
- package/esm/http/http-response.js +19 -0
- package/esm/http/index.d.ts +13 -2
- package/esm/http/index.js +13 -2
- package/esm/http/interfaces/client-http-headers.interface.d.ts +1 -1
- package/esm/http/interfaces/server-http-headers.interface.d.ts +1 -1
- package/esm/http/multipart/batch-multipart.d.ts +1 -1
- package/esm/http/multipart/batch-multipart.js +12 -12
- package/esm/http/multipart/http-request-content.d.ts +1 -1
- package/esm/http/multipart/http-response-content.d.ts +1 -1
- package/esm/http/param-codec/boolean-codec.d.ts +5 -0
- package/esm/http/param-codec/boolean-codec.js +21 -0
- package/esm/http/param-codec/date-codec.d.ts +16 -0
- package/esm/http/param-codec/date-codec.js +40 -0
- package/esm/http/param-codec/filter-codec.d.ts +6 -0
- package/esm/http/param-codec/filter-codec.js +14 -0
- package/esm/http/param-codec/integer-codec.d.ts +9 -0
- package/esm/http/param-codec/integer-codec.js +15 -0
- package/esm/http/param-codec/number-codec.d.ts +12 -0
- package/esm/http/param-codec/number-codec.js +22 -0
- package/esm/http/param-codec/string-codec.d.ts +14 -0
- package/esm/http/param-codec/string-codec.js +21 -0
- package/esm/http/utils/encodeURIParam.d.ts +1 -0
- package/esm/http/utils/encodeURIParam.js +17 -0
- package/esm/http/utils/normalize-headers.js +2 -2
- package/esm/i18n/i18n.d.ts +6 -6
- package/esm/i18n/i18n.js +1 -4
- package/esm/schema/decorators/opr-collection-resource.decorator.d.ts +1 -1
- package/esm/schema/decorators/opr-complex-type.decorator.d.ts +1 -1
- package/esm/schema/decorators/opr-simple-type.decorator.d.ts +1 -1
- package/esm/schema/decorators/opr-singleton-resource.decorator.d.ts +1 -1
- package/esm/schema/implementation/data-type/complex-type.d.ts +1 -1
- package/esm/schema/implementation/data-type/union-type.d.ts +1 -1
- package/esm/schema/implementation/document-builder.d.ts +1 -1
- package/esm/schema/implementation/opra-document.d.ts +2 -2
- package/esm/schema/implementation/opra-document.js +12 -11
- package/esm/schema/implementation/query/collection-count-query.d.ts +1 -1
- package/esm/schema/implementation/query/collection-create-query.d.ts +1 -1
- package/esm/schema/implementation/query/collection-delete-many-query.d.ts +1 -1
- package/esm/schema/implementation/query/collection-get-query.d.ts +1 -1
- package/esm/schema/implementation/query/collection-search-query.d.ts +1 -1
- package/esm/schema/implementation/query/collection-update-many-query.d.ts +1 -1
- package/esm/schema/implementation/query/collection-update-query.d.ts +1 -1
- package/esm/schema/implementation/query/field-get-query.d.ts +1 -1
- package/esm/schema/implementation/query/index.d.ts +4 -4
- package/esm/schema/implementation/query/singleton-get-query.d.ts +1 -1
- package/esm/schema/implementation/resource/collection-resource-info.d.ts +2 -0
- package/esm/schema/implementation/resource/collection-resource-info.js +7 -0
- package/esm/schema/interfaces/data-type.metadata.d.ts +4 -4
- package/esm/schema/interfaces/resource.metadata.d.ts +9 -9
- package/esm/schema/types.d.ts +8 -8
- package/esm/url/opra-url-path-component.d.ts +1 -1
- package/esm/url/opra-url-path.d.ts +24 -18
- package/esm/url/opra-url-path.js +96 -72
- package/esm/url/opra-url-search-params.d.ts +3 -42
- package/esm/url/opra-url-search-params.js +16 -234
- package/esm/url/opra-url.d.ts +38 -28
- package/esm/url/opra-url.js +201 -160
- package/package.json +12 -12
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a, _b, _c;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.HttpParams = void 0;
|
|
5
|
+
const fast_tokenizer_1 = require("fast-tokenizer");
|
|
6
|
+
const responsive_map_js_1 = require("../helpers/responsive-map.js");
|
|
7
|
+
const boolean_codec_js_1 = require("./param-codec/boolean-codec.js");
|
|
8
|
+
const date_codec_js_1 = require("./param-codec/date-codec.js");
|
|
9
|
+
const filter_codec_js_1 = require("./param-codec/filter-codec.js");
|
|
10
|
+
const integer_codec_js_1 = require("./param-codec/integer-codec.js");
|
|
11
|
+
const number_codec_js_1 = require("./param-codec/number-codec.js");
|
|
12
|
+
const string_codec_js_1 = require("./param-codec/string-codec.js");
|
|
13
|
+
const encodeURIParam_js_1 = require("./utils/encodeURIParam.js");
|
|
14
|
+
const kEntries = Symbol('kEntries');
|
|
15
|
+
const kSize = Symbol('kSize');
|
|
16
|
+
const kParamDefs = Symbol('kParamDefs');
|
|
17
|
+
const kOptions = Symbol('kOptions');
|
|
18
|
+
const defaultKeyDecoder = (s) => decodeURIComponent(s);
|
|
19
|
+
const defaultValueDecoder = (s) => decodeURIComponent(s);
|
|
20
|
+
const defaultKeyEncoder = (s) => (0, encodeURIParam_js_1.encodeURIParam)(s);
|
|
21
|
+
const defaultValueEncoder = (s) => (0, encodeURIParam_js_1.encodeURIParam)(s);
|
|
22
|
+
const internalCodecs = {
|
|
23
|
+
'boolean': new boolean_codec_js_1.BooleanCodec(),
|
|
24
|
+
'date': new date_codec_js_1.DateCodec(),
|
|
25
|
+
'filter': new filter_codec_js_1.FilterCodec(),
|
|
26
|
+
'integer': new integer_codec_js_1.IntegerCodec(),
|
|
27
|
+
'number': new number_codec_js_1.NumberCodec(),
|
|
28
|
+
'string': new string_codec_js_1.StringCodec()
|
|
29
|
+
};
|
|
30
|
+
class HttpParams {
|
|
31
|
+
constructor(init, options) {
|
|
32
|
+
this[_a] = new responsive_map_js_1.ResponsiveMap();
|
|
33
|
+
this[_b] = 0;
|
|
34
|
+
this[_c] = new Map();
|
|
35
|
+
this[kOptions] = { ...options, onChange: undefined };
|
|
36
|
+
const defineParams = options?.params;
|
|
37
|
+
if (defineParams)
|
|
38
|
+
Object.keys(defineParams).forEach(key => this.define(key, defineParams[key]));
|
|
39
|
+
if (init)
|
|
40
|
+
this.appendAll(init);
|
|
41
|
+
this[kOptions].onChange = options?.onChange;
|
|
42
|
+
}
|
|
43
|
+
get size() {
|
|
44
|
+
return this[kSize];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Appends a new value to the existing set of values for a parameter
|
|
48
|
+
* and returns this instance
|
|
49
|
+
*/
|
|
50
|
+
append(name, value) {
|
|
51
|
+
this._append(name, value);
|
|
52
|
+
this.changed();
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
appendAll(input) {
|
|
56
|
+
if (typeof input === 'string') {
|
|
57
|
+
if (input && input.startsWith('?'))
|
|
58
|
+
input = input.substring(1);
|
|
59
|
+
if (!input)
|
|
60
|
+
return this;
|
|
61
|
+
const tokenizer = (0, fast_tokenizer_1.tokenize)(input, { delimiters: '&', quotes: true, brackets: true });
|
|
62
|
+
for (const token of tokenizer) {
|
|
63
|
+
if (!token)
|
|
64
|
+
continue;
|
|
65
|
+
const itemTokenizer = (0, fast_tokenizer_1.tokenize)(token, {
|
|
66
|
+
delimiters: '=',
|
|
67
|
+
quotes: true,
|
|
68
|
+
brackets: true
|
|
69
|
+
});
|
|
70
|
+
const k = this.decodeKey(itemTokenizer.next() || '');
|
|
71
|
+
const v = this.decodeValue(itemTokenizer.join('='), k);
|
|
72
|
+
this._append(k, v);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else if (input.forEach && typeof input.forEach === 'function')
|
|
76
|
+
input.forEach((value, name) => this._append(name, value));
|
|
77
|
+
else
|
|
78
|
+
Object.keys(input).forEach(name => this._append(name, input[name]));
|
|
79
|
+
return this;
|
|
80
|
+
}
|
|
81
|
+
changed() {
|
|
82
|
+
if (this[kOptions].onChange)
|
|
83
|
+
this[kOptions].onChange();
|
|
84
|
+
}
|
|
85
|
+
clear() {
|
|
86
|
+
if (this[kEntries].size) {
|
|
87
|
+
this[kEntries].clear();
|
|
88
|
+
this[kSize] = 0;
|
|
89
|
+
this.changed();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Deletes values for a given parameter
|
|
94
|
+
*/
|
|
95
|
+
delete(name, value) {
|
|
96
|
+
if (this._delete(name, value))
|
|
97
|
+
this.changed();
|
|
98
|
+
return this;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Returns an iterable of key, value pairs for every entry in the map.
|
|
102
|
+
*/
|
|
103
|
+
entries() {
|
|
104
|
+
const iter = this[kEntries].entries();
|
|
105
|
+
let i = 0;
|
|
106
|
+
let key;
|
|
107
|
+
let values;
|
|
108
|
+
return {
|
|
109
|
+
[Symbol.iterator]() {
|
|
110
|
+
return this;
|
|
111
|
+
},
|
|
112
|
+
next() {
|
|
113
|
+
if (values) {
|
|
114
|
+
if (i >= values.length) {
|
|
115
|
+
values = undefined;
|
|
116
|
+
i = 0;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (!values) {
|
|
120
|
+
const n = iter.next();
|
|
121
|
+
if (n.done)
|
|
122
|
+
return { done: true, value: undefined };
|
|
123
|
+
key = n.value[0];
|
|
124
|
+
values = n.value[1];
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
done: false,
|
|
128
|
+
value: [key, values[i++]]
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
forEach(callbackFn, thisArg) {
|
|
134
|
+
const iterator = this.entries();
|
|
135
|
+
let entry = iterator.next();
|
|
136
|
+
while (!entry.done) {
|
|
137
|
+
callbackFn.call(thisArg || this, entry.value[1], entry.value[0], this);
|
|
138
|
+
entry = iterator.next();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Retrieves value of a given parameter at given index
|
|
143
|
+
*/
|
|
144
|
+
get(name, index = 0) {
|
|
145
|
+
const values = this[kEntries].get(name.toLowerCase());
|
|
146
|
+
return values && values.length > index ? values[index] : null;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Retrieves an array of values for a given parameter.
|
|
150
|
+
*/
|
|
151
|
+
getAll(name) {
|
|
152
|
+
const entry = this[kEntries].get(name);
|
|
153
|
+
return entry ? entry.slice(0) : null;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Retrieves the names of the parameters.
|
|
157
|
+
*/
|
|
158
|
+
keys() {
|
|
159
|
+
return this[kEntries].keys();
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Retrieves the names of the parameters.
|
|
163
|
+
*/
|
|
164
|
+
values() {
|
|
165
|
+
const items = [];
|
|
166
|
+
this.forEach((value) => items.push(value));
|
|
167
|
+
return items.values();
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Checks for existence of a parameter.
|
|
171
|
+
*/
|
|
172
|
+
has(name) {
|
|
173
|
+
return this[kEntries].has(name);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Sets or modifies a value for a given parameter.
|
|
177
|
+
* If the header already exists, its value is replaced with the given value
|
|
178
|
+
*/
|
|
179
|
+
set(name, value) {
|
|
180
|
+
this._set(name, value);
|
|
181
|
+
this.changed();
|
|
182
|
+
return this;
|
|
183
|
+
}
|
|
184
|
+
sort(compareFn) {
|
|
185
|
+
this[kEntries].sort(compareFn);
|
|
186
|
+
this.changed();
|
|
187
|
+
return this;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Serializes the body to an encoded string, where key-value pairs (separated by `=`) are
|
|
191
|
+
* separated by `&`s.
|
|
192
|
+
*/
|
|
193
|
+
toString() {
|
|
194
|
+
const out = [];
|
|
195
|
+
this.forEach((v, k) => {
|
|
196
|
+
out.push(this.encodeKey(k) +
|
|
197
|
+
(v ? '=' + this.encodeValue(v, k) : ''));
|
|
198
|
+
});
|
|
199
|
+
return out.join('&');
|
|
200
|
+
}
|
|
201
|
+
define(name, options) {
|
|
202
|
+
if (!name)
|
|
203
|
+
throw new Error('Parameter name required');
|
|
204
|
+
if (typeof options?.codec === 'string' && !internalCodecs[options.codec])
|
|
205
|
+
throw new Error(`Unknown url parameter format name "${options.codec}"`);
|
|
206
|
+
const codec = (typeof options?.codec === 'string'
|
|
207
|
+
? internalCodecs[options.codec]
|
|
208
|
+
: options?.codec) || internalCodecs.string;
|
|
209
|
+
const meta = {
|
|
210
|
+
...options,
|
|
211
|
+
codec
|
|
212
|
+
};
|
|
213
|
+
this[kParamDefs].set(name, meta);
|
|
214
|
+
return this;
|
|
215
|
+
}
|
|
216
|
+
encodeKey(key) {
|
|
217
|
+
return (this[kOptions].encodeKey || defaultKeyEncoder)(key);
|
|
218
|
+
}
|
|
219
|
+
decodeKey(key) {
|
|
220
|
+
return (this[kOptions].decodeKey || defaultKeyDecoder)(key);
|
|
221
|
+
}
|
|
222
|
+
encodeValue(value, key) {
|
|
223
|
+
const prmDef = this[kParamDefs].get(key);
|
|
224
|
+
if (prmDef) {
|
|
225
|
+
const delimReplace = '%' + (prmDef.arrayDelimiter || ',').charCodeAt(0).toString(16).toUpperCase();
|
|
226
|
+
const fn = (x) => (0, encodeURIParam_js_1.encodeURIParam)(prmDef.codec.encode(x)).replaceAll(',', delimReplace);
|
|
227
|
+
return Array.isArray(value)
|
|
228
|
+
? value.map((v) => fn(v)).join(prmDef.arrayDelimiter || ',')
|
|
229
|
+
: fn(value);
|
|
230
|
+
}
|
|
231
|
+
return (this[kOptions].encodeValue || defaultValueEncoder)(value);
|
|
232
|
+
}
|
|
233
|
+
decodeValue(value, key) {
|
|
234
|
+
const prmDef = this[kParamDefs].get(key);
|
|
235
|
+
const valueDecoder = (this[kOptions].decodeValue || defaultValueDecoder);
|
|
236
|
+
let val = value;
|
|
237
|
+
if (prmDef) {
|
|
238
|
+
if (prmDef.array) {
|
|
239
|
+
val = (0, fast_tokenizer_1.splitString)(value, {
|
|
240
|
+
delimiters: prmDef.arrayDelimiter || ',',
|
|
241
|
+
brackets: true,
|
|
242
|
+
quotes: true,
|
|
243
|
+
keepQuotes: false
|
|
244
|
+
}).map((x) => valueDecoder(x));
|
|
245
|
+
}
|
|
246
|
+
else
|
|
247
|
+
val = valueDecoder(val);
|
|
248
|
+
const fn = (x) => prmDef.codec.decode(valueDecoder(x));
|
|
249
|
+
val = Array.isArray(val) ? val.map(fn) : fn(val);
|
|
250
|
+
if (prmDef.array === 'strict')
|
|
251
|
+
val = Array.isArray(val) ? val : [val];
|
|
252
|
+
else if (prmDef.array)
|
|
253
|
+
val = Array.isArray(val) && val.length === 1 ? val[0] : val;
|
|
254
|
+
if (Array.isArray(val)) {
|
|
255
|
+
if (prmDef.minArrayItems && val.length < prmDef.minArrayItems)
|
|
256
|
+
throw new Error(`"${key}" parameter requires at least ${prmDef.minArrayItems} values`);
|
|
257
|
+
if (prmDef.maxArrayItems && val.length > prmDef.maxArrayItems)
|
|
258
|
+
throw new Error(`"${key}" parameter accepts up to ${prmDef.maxArrayItems} values`);
|
|
259
|
+
}
|
|
260
|
+
return val;
|
|
261
|
+
}
|
|
262
|
+
return valueDecoder(value);
|
|
263
|
+
}
|
|
264
|
+
_append(name, value) {
|
|
265
|
+
let values = this[kEntries].get(name);
|
|
266
|
+
if (!values) {
|
|
267
|
+
values = [];
|
|
268
|
+
this[kEntries].set(name, values);
|
|
269
|
+
}
|
|
270
|
+
values.push(value ?? null);
|
|
271
|
+
this[kSize] += 1;
|
|
272
|
+
}
|
|
273
|
+
_delete(name, value) {
|
|
274
|
+
const oldValues = this[kEntries].get(name);
|
|
275
|
+
if (!oldValues)
|
|
276
|
+
return false;
|
|
277
|
+
const oldSize = this[kSize];
|
|
278
|
+
if (value) {
|
|
279
|
+
const valueToDelete = Array.isArray(value) ? value : [value];
|
|
280
|
+
const newValues = oldValues.filter(x => !valueToDelete.includes(x));
|
|
281
|
+
this[kEntries].set(name, newValues);
|
|
282
|
+
this[kSize] += -oldValues.length + newValues.length;
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
this[kEntries].delete(name);
|
|
286
|
+
this[kSize] -= oldValues.length;
|
|
287
|
+
}
|
|
288
|
+
return oldSize !== this[kSize];
|
|
289
|
+
}
|
|
290
|
+
_set(name, value, index) {
|
|
291
|
+
if (value == null) {
|
|
292
|
+
this._delete(name);
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
const values = this[kEntries].get(name);
|
|
296
|
+
if (!values) {
|
|
297
|
+
this[kEntries].set(name, [value]);
|
|
298
|
+
this[kSize] += 1;
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
if (index == null || index < 0) {
|
|
302
|
+
this[kEntries].set(name, [value]);
|
|
303
|
+
this[kSize] += -(values.length) + 1;
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
const oldLen = values.length;
|
|
307
|
+
values[Math.min(index, values.length)] = value;
|
|
308
|
+
this[kSize] += -oldLen + values.length;
|
|
309
|
+
}
|
|
310
|
+
[(_a = kEntries, _b = kSize, _c = kParamDefs, Symbol.iterator)]() {
|
|
311
|
+
return this.entries();
|
|
312
|
+
}
|
|
313
|
+
get [Symbol.toStringTag]() {
|
|
314
|
+
return 'HttpParams';
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
exports.HttpParams = HttpParams;
|
|
318
|
+
HttpParams.kEntries = kEntries;
|
|
319
|
+
HttpParams.kSize = kSize;
|
|
320
|
+
HttpParams.kParamDefs = kParamDefs;
|
|
321
|
+
HttpParams.kOptions = kOptions;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpRequestNode = void 0;
|
|
4
|
+
const http_parser_js_1 = require("http-parser-js");
|
|
5
|
+
const stream_1 = require("stream");
|
|
6
|
+
const crlfBuffer = Buffer.from('\r\n');
|
|
7
|
+
const kHeaders = Symbol('kHeaders');
|
|
8
|
+
const kHeadersCount = Symbol('kHeadersCount');
|
|
9
|
+
const kTrailers = Symbol('kTrailers');
|
|
10
|
+
const kTrailersCount = Symbol('kTrailersCount');
|
|
11
|
+
// todo: Check is this class should be in common library
|
|
12
|
+
class HttpRequestNode extends stream_1.Readable {
|
|
13
|
+
constructor() {
|
|
14
|
+
super(...arguments);
|
|
15
|
+
this.aborted = false;
|
|
16
|
+
}
|
|
17
|
+
get headers() {
|
|
18
|
+
if (!this[kHeaders])
|
|
19
|
+
this[kHeaders] = arrayToHeaders(this.rawHeaders);
|
|
20
|
+
return this[kHeaders];
|
|
21
|
+
}
|
|
22
|
+
get headersCount() {
|
|
23
|
+
return this[kHeadersCount];
|
|
24
|
+
}
|
|
25
|
+
get trailers() {
|
|
26
|
+
if (!this[kTrailers])
|
|
27
|
+
this[kTrailers] = arrayToHeaders(this.rawTrailers);
|
|
28
|
+
return this[kTrailers];
|
|
29
|
+
}
|
|
30
|
+
get trailersCount() {
|
|
31
|
+
return this[kTrailersCount];
|
|
32
|
+
}
|
|
33
|
+
_read() {
|
|
34
|
+
if (this.data) {
|
|
35
|
+
this.push(this.data);
|
|
36
|
+
}
|
|
37
|
+
this.push(null);
|
|
38
|
+
}
|
|
39
|
+
static parse(input) {
|
|
40
|
+
const parser = new http_parser_js_1.HTTPParser(http_parser_js_1.HTTPParser.REQUEST);
|
|
41
|
+
const out = new HttpRequestNode();
|
|
42
|
+
const bodyChunks = [];
|
|
43
|
+
parser[http_parser_js_1.HTTPParser.kOnHeadersComplete] = function (req) {
|
|
44
|
+
out.shouldKeepAlive = req.shouldKeepAlive;
|
|
45
|
+
out.upgrade = req.upgrade;
|
|
46
|
+
out.method = http_parser_js_1.HTTPParser.methods[req.method];
|
|
47
|
+
out.url = req.url;
|
|
48
|
+
out.originalUrl = req.url;
|
|
49
|
+
out.httpVersionMajor = req.versionMajor;
|
|
50
|
+
out.httpVersionMinor = req.versionMinor;
|
|
51
|
+
out.httpVersion = req.versionMajor + '.' + req.versionMinor;
|
|
52
|
+
out.rawHeaders = req.headers;
|
|
53
|
+
out[kHeadersCount] = Math.ceil(req.headers.length / 2);
|
|
54
|
+
out[kTrailersCount] = 0;
|
|
55
|
+
};
|
|
56
|
+
parser[http_parser_js_1.HTTPParser.kOnBody] = function (chunk, offset, length) {
|
|
57
|
+
bodyChunks.push(chunk.subarray(offset, offset + length));
|
|
58
|
+
};
|
|
59
|
+
// This is actually the event for trailers, go figure.
|
|
60
|
+
parser[http_parser_js_1.HTTPParser.kOnHeaders] = function (t) {
|
|
61
|
+
out.rawTrailers = t;
|
|
62
|
+
out[kTrailersCount] = Math.ceil(t.length / 2);
|
|
63
|
+
};
|
|
64
|
+
parser[http_parser_js_1.HTTPParser.kOnMessageComplete] = function () {
|
|
65
|
+
out.complete = true;
|
|
66
|
+
};
|
|
67
|
+
// Since we are sending the entire Buffer at once here all callbacks above happen synchronously.
|
|
68
|
+
// The parser does not do _anything_ asynchronous.
|
|
69
|
+
// However, you can of course call execute() multiple times with multiple chunks, e.g. from a stream.
|
|
70
|
+
// But then you have to refactor the entire logic to be async (e.g. resolve a Promise in kOnMessageComplete and add timeout logic).
|
|
71
|
+
parser.execute(input);
|
|
72
|
+
if (!out.complete)
|
|
73
|
+
parser.execute(crlfBuffer);
|
|
74
|
+
parser.finish();
|
|
75
|
+
if (!out.complete) {
|
|
76
|
+
throw new Error('Could not parse request');
|
|
77
|
+
}
|
|
78
|
+
out.rawTrailers = out.rawTrailers || [];
|
|
79
|
+
if (bodyChunks.length)
|
|
80
|
+
out.data = Buffer.concat(bodyChunks);
|
|
81
|
+
out.resume();
|
|
82
|
+
return out;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.HttpRequestNode = HttpRequestNode;
|
|
86
|
+
function arrayToHeaders(arr) {
|
|
87
|
+
const headers = {};
|
|
88
|
+
for (let i = 0; i < arr.length; i++) {
|
|
89
|
+
const k = arr[i].toLowerCase();
|
|
90
|
+
const v = arr[++i];
|
|
91
|
+
const trgV = headers[k];
|
|
92
|
+
// Array header -- only Set-Cookie at the moment
|
|
93
|
+
if (trgV && k === 'set-cookie') {
|
|
94
|
+
const a = Array.isArray(trgV) ? trgV : [trgV];
|
|
95
|
+
a.push(v);
|
|
96
|
+
headers[k] = a;
|
|
97
|
+
}
|
|
98
|
+
else if (typeof trgV === 'string') {
|
|
99
|
+
headers[k] += (k === 'cookie' ? '; ' : ', ') + v;
|
|
100
|
+
}
|
|
101
|
+
else
|
|
102
|
+
headers[k] = v;
|
|
103
|
+
}
|
|
104
|
+
return headers;
|
|
105
|
+
}
|
package/cjs/http/http-request.js
CHANGED
|
@@ -1,104 +1,89 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.HttpRequest = void 0;
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
this.
|
|
4
|
+
/// <reference lib="dom" />
|
|
5
|
+
const index_js_1 = require("../url/index.js");
|
|
6
|
+
const http_headers_js_1 = require("./http-headers.js");
|
|
7
|
+
const directCopyProperties = ['cache', 'credentials', 'destination', 'headers', 'integrity',
|
|
8
|
+
'keepalive', 'mode', 'redirect', 'referrer', 'referrerPolicy'];
|
|
9
|
+
class HttpRequest {
|
|
10
|
+
constructor(init) {
|
|
11
|
+
this.cache = init?.cache || 'default';
|
|
12
|
+
this.credentials = init?.credentials || 'same-origin';
|
|
13
|
+
this.destination = init?.destination || '';
|
|
14
|
+
this.headers = new http_headers_js_1.HttpHeaders(init?.headers);
|
|
15
|
+
this.integrity = init?.integrity || '';
|
|
16
|
+
this.keepalive = init?.keepalive ?? false;
|
|
17
|
+
this.method = (init?.method || 'GET').toUpperCase();
|
|
18
|
+
this.mode = init?.mode || 'cors';
|
|
19
|
+
this.redirect = init?.redirect || 'follow';
|
|
20
|
+
this.mode = init?.mode || 'cors';
|
|
21
|
+
this.referrer = init?.referrer || '';
|
|
22
|
+
this.referrerPolicy = init?.referrerPolicy || '';
|
|
23
|
+
this.signal = init?.signal || new AbortController().signal;
|
|
24
|
+
this.body = init?.body;
|
|
25
|
+
this.urlInstance = new index_js_1.OpraURL(init?.url);
|
|
26
|
+
if (init?.params)
|
|
27
|
+
this.params.appendAll(init.params);
|
|
15
28
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return this[kHeaders];
|
|
29
|
+
/** Returns the URL of request as a string. */
|
|
30
|
+
get url() {
|
|
31
|
+
return this.urlInstance.href;
|
|
20
32
|
}
|
|
21
|
-
|
|
22
|
-
|
|
33
|
+
set url(value) {
|
|
34
|
+
this.urlInstance.parse(value);
|
|
23
35
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return this[kTrailers];
|
|
36
|
+
/** Returns the searchParams of the URL as OpraURLSearchParams */
|
|
37
|
+
get params() {
|
|
38
|
+
return this.urlInstance.searchParams;
|
|
28
39
|
}
|
|
29
|
-
|
|
30
|
-
|
|
40
|
+
/** Returns the path part of URL as OpraURLPath */
|
|
41
|
+
get path() {
|
|
42
|
+
return this.urlInstance.path;
|
|
31
43
|
}
|
|
32
|
-
|
|
33
|
-
if (this.data) {
|
|
34
|
-
this.push(this.data);
|
|
35
|
-
}
|
|
36
|
-
this.push(null);
|
|
37
|
-
}
|
|
38
|
-
static parse(input) {
|
|
39
|
-
const parser = new http_parser_js_1.HTTPParser(http_parser_js_1.HTTPParser.REQUEST);
|
|
44
|
+
clone(...update) {
|
|
40
45
|
const out = new HttpRequest();
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
out.
|
|
44
|
-
out.upgrade = req.upgrade;
|
|
45
|
-
out.method = http_parser_js_1.HTTPParser.methods[req.method];
|
|
46
|
-
out.url = req.url;
|
|
47
|
-
out.originalUrl = req.url;
|
|
48
|
-
out.httpVersionMajor = req.versionMajor;
|
|
49
|
-
out.httpVersionMinor = req.versionMinor;
|
|
50
|
-
out.httpVersion = req.versionMajor + '.' + req.versionMinor;
|
|
51
|
-
out.rawHeaders = req.headers;
|
|
52
|
-
out[kHeadersCount] = Math.ceil(req.headers.length / 2);
|
|
53
|
-
out[kTrailersCount] = 0;
|
|
54
|
-
};
|
|
55
|
-
parser[http_parser_js_1.HTTPParser.kOnBody] = function (chunk, offset, length) {
|
|
56
|
-
bodyChunks.push(chunk.subarray(offset, offset + length));
|
|
57
|
-
};
|
|
58
|
-
// This is actually the event for trailers, go figure.
|
|
59
|
-
parser[http_parser_js_1.HTTPParser.kOnHeaders] = function (t) {
|
|
60
|
-
out.rawTrailers = t;
|
|
61
|
-
out[kTrailersCount] = Math.ceil(t.length / 2);
|
|
62
|
-
};
|
|
63
|
-
parser[http_parser_js_1.HTTPParser.kOnMessageComplete] = function () {
|
|
64
|
-
out.complete = true;
|
|
65
|
-
};
|
|
66
|
-
// Since we are sending the entire Buffer at once here all callbacks above happen synchronously.
|
|
67
|
-
// The parser does not do _anything_ asynchronous.
|
|
68
|
-
// However, you can of course call execute() multiple times with multiple chunks, e.g. from a stream.
|
|
69
|
-
// But then you have to refactor the entire logic to be async (e.g. resolve a Promise in kOnMessageComplete and add timeout logic).
|
|
70
|
-
parser.execute(input);
|
|
71
|
-
if (!out.complete)
|
|
72
|
-
parser.execute(crlfBuffer);
|
|
73
|
-
parser.finish();
|
|
74
|
-
if (!out.complete) {
|
|
75
|
-
throw new Error('Could not parse request');
|
|
46
|
+
out.merge(this);
|
|
47
|
+
for (const upd of update) {
|
|
48
|
+
out.merge(upd);
|
|
76
49
|
}
|
|
77
|
-
out.rawTrailers = out.rawTrailers || [];
|
|
78
|
-
if (bodyChunks.length)
|
|
79
|
-
out.data = Buffer.concat(bodyChunks);
|
|
80
|
-
out.resume();
|
|
81
50
|
return out;
|
|
82
51
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
52
|
+
merge(update) {
|
|
53
|
+
directCopyProperties.forEach(k => {
|
|
54
|
+
if (update[k] != null)
|
|
55
|
+
this[k] = update[k];
|
|
56
|
+
});
|
|
57
|
+
if (update.headers) {
|
|
58
|
+
const h = update.headers instanceof http_headers_js_1.HttpHeaders
|
|
59
|
+
? update.headers
|
|
60
|
+
: new http_headers_js_1.HttpHeaders(update.headers);
|
|
61
|
+
h.forEach((v, k) => {
|
|
62
|
+
if (k.toLowerCase() === 'set-cookie') {
|
|
63
|
+
this.headers.append(k, v);
|
|
64
|
+
}
|
|
65
|
+
else
|
|
66
|
+
this.headers.set(k, v);
|
|
67
|
+
});
|
|
96
68
|
}
|
|
97
|
-
|
|
98
|
-
|
|
69
|
+
}
|
|
70
|
+
inset(src) {
|
|
71
|
+
directCopyProperties.forEach(k => {
|
|
72
|
+
if (this[k] == null && src[k] != null)
|
|
73
|
+
this[k] = src[k];
|
|
74
|
+
});
|
|
75
|
+
if (src.headers) {
|
|
76
|
+
const h = src.headers instanceof http_headers_js_1.HttpHeaders
|
|
77
|
+
? src.headers
|
|
78
|
+
: new http_headers_js_1.HttpHeaders(src.headers);
|
|
79
|
+
h.forEach((v, k) => {
|
|
80
|
+
if (k.toLowerCase() === 'set-cookie') {
|
|
81
|
+
this.headers.append(k, v);
|
|
82
|
+
}
|
|
83
|
+
else if (!this.headers.has(k))
|
|
84
|
+
this.headers.set(k, v);
|
|
85
|
+
});
|
|
99
86
|
}
|
|
100
|
-
else
|
|
101
|
-
headers[k] = v;
|
|
102
87
|
}
|
|
103
|
-
return headers;
|
|
104
88
|
}
|
|
89
|
+
exports.HttpRequest = HttpRequest;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpResponse = void 0;
|
|
4
|
+
const http_headers_js_1 = require("./http-headers.js");
|
|
5
|
+
class HttpResponse {
|
|
6
|
+
constructor(init) {
|
|
7
|
+
/**
|
|
8
|
+
* Returns true if response has body to be received
|
|
9
|
+
*/
|
|
10
|
+
this.hasBody = false;
|
|
11
|
+
this.headers = new http_headers_js_1.HttpHeaders(init?.headers);
|
|
12
|
+
this.status = init?.status || 200;
|
|
13
|
+
this.statusText = init?.statusText || 'OK';
|
|
14
|
+
this.url = init?.url || null;
|
|
15
|
+
this.ok = this.status >= 200 && this.status < 300;
|
|
16
|
+
this.body = init?.body;
|
|
17
|
+
this.hasBody = init?.body != null || !!init?.hasBody;
|
|
18
|
+
}
|
|
19
|
+
clone(update) {
|
|
20
|
+
return new HttpResponse({ ...this, ...update });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.HttpResponse = HttpResponse;
|
package/cjs/http/index.js
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const tslib_1 = require("tslib");
|
|
4
|
+
tslib_1.__exportStar(require("./http-request-node.js"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./http-headers.js"), exports);
|
|
4
6
|
tslib_1.__exportStar(require("./http-request.js"), exports);
|
|
5
|
-
tslib_1.__exportStar(require("./
|
|
6
|
-
tslib_1.__exportStar(require("./
|
|
7
|
+
tslib_1.__exportStar(require("./http-response.js"), exports);
|
|
8
|
+
tslib_1.__exportStar(require("./http-params.js"), exports);
|
|
9
|
+
tslib_1.__exportStar(require("./http-param-codec.js"), exports);
|
|
10
|
+
tslib_1.__exportStar(require("./enums/http-headers-codes.enum.js"), exports);
|
|
11
|
+
tslib_1.__exportStar(require("./enums/http-status-codes.enum.js"), exports);
|
|
7
12
|
tslib_1.__exportStar(require("./interfaces/client-http-headers.interface.js"), exports);
|
|
8
13
|
tslib_1.__exportStar(require("./interfaces/server-http-headers.interface.js"), exports);
|
|
14
|
+
tslib_1.__exportStar(require("./param-codec/date-codec.js"), exports);
|
|
15
|
+
tslib_1.__exportStar(require("./param-codec/boolean-codec.js"), exports);
|
|
16
|
+
tslib_1.__exportStar(require("./param-codec/filter-codec.js"), exports);
|
|
17
|
+
tslib_1.__exportStar(require("./param-codec/integer-codec.js"), exports);
|
|
18
|
+
tslib_1.__exportStar(require("./param-codec/number-codec.js"), exports);
|
|
19
|
+
tslib_1.__exportStar(require("./param-codec/string-codec.js"), exports);
|
|
9
20
|
tslib_1.__exportStar(require("./utils/normalize-headers.js"), exports);
|