@webqit/webflo 0.11.61-0 → 1.0.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/.gitignore +7 -7
- package/LICENSE +20 -20
- package/README.md +2079 -2074
- package/docker/Dockerfile +42 -42
- package/docker/README.md +91 -91
- package/docker/package.json +2 -2
- package/package.json +80 -81
- package/src/{Context.js → AbstractContext.js} +71 -79
- package/src/config-pi/deployment/Env.js +68 -68
- package/src/config-pi/deployment/Layout.js +63 -63
- package/src/config-pi/deployment/Origins.js +139 -139
- package/src/config-pi/deployment/Proxy.js +74 -74
- package/src/config-pi/deployment/index.js +17 -17
- package/src/config-pi/index.js +15 -15
- package/src/config-pi/runtime/Client.js +116 -98
- package/src/config-pi/runtime/Server.js +125 -125
- package/src/config-pi/runtime/client/Worker.js +109 -134
- package/src/config-pi/runtime/client/index.js +11 -11
- package/src/config-pi/runtime/index.js +17 -17
- package/src/config-pi/runtime/server/Headers.js +74 -74
- package/src/config-pi/runtime/server/Redirects.js +69 -69
- package/src/config-pi/runtime/server/index.js +13 -13
- package/src/config-pi/static/Manifest.js +319 -319
- package/src/config-pi/static/Ssg.js +49 -49
- package/src/config-pi/static/index.js +13 -13
- package/src/deployment-pi/index.js +10 -10
- package/src/deployment-pi/origins/index.js +216 -216
- package/src/index.js +11 -19
- package/src/runtime-pi/HttpEvent.js +126 -106
- package/src/runtime-pi/HttpUser.js +126 -0
- package/src/runtime-pi/MessagingOverBroadcast.js +9 -0
- package/src/runtime-pi/MessagingOverChannel.js +85 -0
- package/src/runtime-pi/MessagingOverSocket.js +106 -0
- package/src/runtime-pi/MultiportMessagingAPI.js +81 -0
- package/src/runtime-pi/WebfloCookieStorage.js +27 -0
- package/src/runtime-pi/WebfloEventTarget.js +39 -0
- package/src/runtime-pi/WebfloMessageEvent.js +58 -0
- package/src/runtime-pi/WebfloMessagingAPI.js +69 -0
- package/src/runtime-pi/{Router.js → WebfloRouter.js} +99 -130
- package/src/runtime-pi/WebfloRuntime.js +52 -0
- package/src/runtime-pi/WebfloStorage.js +109 -0
- package/src/runtime-pi/client/ClientMessaging.js +5 -0
- package/src/runtime-pi/client/Context.js +3 -7
- package/src/runtime-pi/client/CookieStorage.js +17 -0
- package/src/runtime-pi/client/Router.js +38 -48
- package/src/runtime-pi/client/SessionStorage.js +33 -0
- package/src/runtime-pi/client/Url.js +156 -205
- package/src/runtime-pi/client/WebfloClient.js +544 -0
- package/src/runtime-pi/client/WebfloRootClient1.js +179 -0
- package/src/runtime-pi/client/WebfloRootClient2.js +109 -0
- package/src/runtime-pi/client/WebfloSubClient.js +165 -0
- package/src/runtime-pi/client/Workport.js +118 -178
- package/src/runtime-pi/client/generate.js +480 -471
- package/src/runtime-pi/client/index.js +16 -21
- package/src/runtime-pi/client/worker/ClientMessaging.js +5 -0
- package/src/runtime-pi/client/worker/Context.js +3 -7
- package/src/runtime-pi/client/worker/CookieStorage.js +17 -0
- package/src/runtime-pi/client/worker/SessionStorage.js +13 -0
- package/src/runtime-pi/client/worker/WebfloWorker.js +294 -0
- package/src/runtime-pi/client/worker/Workport.js +17 -85
- package/src/runtime-pi/client/worker/index.js +10 -21
- package/src/runtime-pi/index.js +6 -13
- package/src/runtime-pi/server/ClientMessaging.js +18 -0
- package/src/runtime-pi/server/ClientMessagingRegistry.js +57 -0
- package/src/runtime-pi/server/Context.js +11 -15
- package/src/runtime-pi/server/CookieStorage.js +17 -0
- package/src/runtime-pi/server/Router.js +93 -159
- package/src/runtime-pi/server/SessionStorage.js +53 -0
- package/src/runtime-pi/server/WebfloServer.js +755 -0
- package/src/runtime-pi/server/index.js +10 -21
- package/src/runtime-pi/util-http.js +322 -86
- package/src/runtime-pi/util-url.js +146 -146
- package/src/runtime-pi/xURL.js +108 -105
- package/src/runtime-pi/xfetch.js +22 -22
- package/src/services-pi/cert/http-auth-hook.js +22 -22
- package/src/services-pi/cert/http-cleanup-hook.js +22 -22
- package/src/services-pi/cert/index.js +79 -79
- package/src/services-pi/index.js +8 -8
- package/src/static-pi/index.js +10 -10
- package/src/webflo.js +30 -30
- package/test/index.test.js +26 -26
- package/test/site/package.json +9 -9
- package/test/site/public/bundle.html +5 -5
- package/test/site/public/bundle.html.json +3 -3
- package/test/site/public/bundle.js +2 -2
- package/test/site/public/bundle.webflo.js +15 -15
- package/test/site/public/index.html +29 -29
- package/test/site/public/index1.html +34 -34
- package/test/site/public/page-2/bundle.html +4 -4
- package/test/site/public/page-2/bundle.js +2 -2
- package/test/site/public/page-2/index.html +45 -45
- package/test/site/public/page-2/main.html +2 -2
- package/test/site/public/page-4/subpage/bundle.js +2 -2
- package/test/site/public/page-4/subpage/index.html +30 -30
- package/test/site/public/sparoots.json +4 -4
- package/test/site/public/worker.js +3 -3
- package/test/site/server/index.js +15 -15
- package/src/runtime-pi/Application.js +0 -29
- package/src/runtime-pi/Cookies.js +0 -82
- package/src/runtime-pi/Runtime.js +0 -21
- package/src/runtime-pi/client/Application.js +0 -100
- package/src/runtime-pi/client/Runtime.js +0 -332
- package/src/runtime-pi/client/createStorage.js +0 -57
- package/src/runtime-pi/client/oohtml/full.js +0 -7
- package/src/runtime-pi/client/oohtml/namespacing.js +0 -7
- package/src/runtime-pi/client/oohtml/scripting.js +0 -8
- package/src/runtime-pi/client/oohtml/templating.js +0 -8
- package/src/runtime-pi/client/worker/Application.js +0 -44
- package/src/runtime-pi/client/worker/Runtime.js +0 -269
- package/src/runtime-pi/server/Application.js +0 -116
- package/src/runtime-pi/server/Runtime.js +0 -557
- package/src/runtime-pi/xFormData.js +0 -24
- package/src/runtime-pi/xHeaders.js +0 -146
- package/src/runtime-pi/xRequest.js +0 -46
- package/src/runtime-pi/xRequestHeaders.js +0 -109
- package/src/runtime-pi/xResponse.js +0 -33
- package/src/runtime-pi/xResponseHeaders.js +0 -117
- package/src/runtime-pi/xxHttpMessage.js +0 -102
|
@@ -1,21 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
*/
|
|
12
|
-
export async function start(applicationInstance = null) {
|
|
13
|
-
const cx = this || {};
|
|
14
|
-
const defaultApplicationInstance = _cx => new Application(_cx);
|
|
15
|
-
return new Runtime(Context.create(cx), applicationInstance || defaultApplicationInstance);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @APIS
|
|
20
|
-
*/
|
|
21
|
-
export * as APIS from './Runtime.js';
|
|
1
|
+
import { WebfloServer } from './WebfloServer.js';
|
|
2
|
+
|
|
3
|
+
export async function start() {
|
|
4
|
+
const instance = WebfloServer.create(this || {});
|
|
5
|
+
await instance.initialize();
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
WebfloServer
|
|
10
|
+
}
|
|
@@ -1,86 +1,322 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
1
|
+
import { _isString, _isNumeric, _isObject, _isPlainObject, _isArray, _isPlainArray, _isTypeObject, _isNumber, _isBoolean } from '@webqit/util/js/index.js';
|
|
2
|
+
import { _after, _before } from '@webqit/util/str/index.js';
|
|
3
|
+
import { _from as _arrFrom } from '@webqit/util/arr/index.js';
|
|
4
|
+
import { params } from './util-url.js';
|
|
5
|
+
|
|
6
|
+
export function dataType(value) {
|
|
7
|
+
if (_isString(value) || _isNumber(value) || _isBoolean(value)) return 'json';
|
|
8
|
+
if (!_isTypeObject(value)) return;
|
|
9
|
+
const toStringTag = value[Symbol.toStringTag];
|
|
10
|
+
const type = [
|
|
11
|
+
'Uint8Array', 'Uint16Array', 'Uint32Array', 'ArrayBuffer', 'Blob', 'File', 'FormData', 'Stream', 'ReadableStream'
|
|
12
|
+
].reduce((_toStringTag, type) => _toStringTag || (toStringTag === type ? type : null), null);
|
|
13
|
+
if (type) return type;
|
|
14
|
+
if ((_isObject(value) && _isPlainObject(value)) || (_isArray(value) && _isPlainArray(value)) || 'toString' in value) {
|
|
15
|
+
return 'json';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function renderHttpMessageInit(httpMessageInit) {
|
|
20
|
+
const headers = (httpMessageInit.headers instanceof Headers) ? [...httpMessageInit.headers.keys()].reduce((_headers, name) => {
|
|
21
|
+
return { ..._headers, [name/* lower-cased */]: httpMessageInit.headers.get(name) };
|
|
22
|
+
}, {}) : Object.keys(httpMessageInit.headers || {}).reduce((_headers, name) => {
|
|
23
|
+
return { ..._headers, [name.toLowerCase()]: httpMessageInit.headers[name] };
|
|
24
|
+
}, {});
|
|
25
|
+
let body = httpMessageInit.body, type = dataType(httpMessageInit.body);
|
|
26
|
+
if (['Blob', 'File'].includes(type)) {
|
|
27
|
+
!headers['content-type'] && (headers['content-type'] = body.type);
|
|
28
|
+
!headers['content-length'] && (headers['content-length'] = body.size);
|
|
29
|
+
} else if (['Uint8Array', 'Uint16Array', 'Uint32Array', 'ArrayBuffer'].includes(type)) {
|
|
30
|
+
!headers['content-length'] && (headers['content-length'] = body.byteLength);
|
|
31
|
+
} else if (type === 'json' && _isTypeObject(body)) {
|
|
32
|
+
if (!headers['content-type']) {
|
|
33
|
+
const [_body, isJsonfiable] = createFormDataFromJson(body, true/*jsonfy*/, true/*getIsJsonfiable*/);
|
|
34
|
+
if (isJsonfiable) {
|
|
35
|
+
body = JSON.stringify(body, (k, v) => v instanceof Error ? { ...v, message: v.message } : v);
|
|
36
|
+
headers['content-type'] = 'application/json';
|
|
37
|
+
headers['content-length'] = (new Blob([body])).size;
|
|
38
|
+
} else {
|
|
39
|
+
body = _body;
|
|
40
|
+
type = 'FormData';
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
} else if (type === 'json') {
|
|
44
|
+
!headers['content-length'] && (headers['content-length'] = (body + '').length);
|
|
45
|
+
}
|
|
46
|
+
return { body, headers, $type: type };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function parseHttpMessage(httpMessage) {
|
|
50
|
+
let result;
|
|
51
|
+
const contentType = httpMessage.headers.get('Content-Type') || '';
|
|
52
|
+
if (contentType === 'application/x-www-form-urlencoded' || contentType.startsWith('multipart/form-data')) {
|
|
53
|
+
const formData = await httpMessage.formData();
|
|
54
|
+
result = await formData?.json();
|
|
55
|
+
} else if (contentType.startsWith('application/json')/*can include charset*/) {
|
|
56
|
+
result = await httpMessage.json();
|
|
57
|
+
} else /*if (contentType === 'text/plain')*/ {
|
|
58
|
+
result = await httpMessage.text();
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function createFormDataFromJson(data = {}, jsonfy = true, getIsJsonfiable = false) {
|
|
64
|
+
const formData = new FormData;
|
|
65
|
+
let isJsonfiable = true;
|
|
66
|
+
params.reduceValue(data, '', (value, contextPath, suggestedKeys = undefined) => {
|
|
67
|
+
if (suggestedKeys) {
|
|
68
|
+
const isJson = dataType(value) === 'json';
|
|
69
|
+
isJsonfiable = isJsonfiable && isJson;
|
|
70
|
+
return isJson && suggestedKeys;
|
|
71
|
+
}
|
|
72
|
+
if (jsonfy && [true, false, null].includes(value)) {
|
|
73
|
+
value = new Blob([value], { type: 'application/json' });
|
|
74
|
+
}
|
|
75
|
+
formData.append(contextPath, value);
|
|
76
|
+
});
|
|
77
|
+
if (getIsJsonfiable) return [formData, isJsonfiable];
|
|
78
|
+
return formData;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export async function renderFormDataToJson(formData, jsonfy = true, getIsJsonfiable = false) {
|
|
82
|
+
let isJsonfiable = true;
|
|
83
|
+
let json;
|
|
84
|
+
for (let [name, value] of formData.entries()) {
|
|
85
|
+
if (!json) { json = _isNumeric(_before(name, '[')) ? [] : {}; }
|
|
86
|
+
let type = dataType(value);
|
|
87
|
+
if (jsonfy && ['Blob', 'File'].includes(type) && value.type === 'application/json' && [4, 5].includes(value.size)) {
|
|
88
|
+
let _value = await value.text();
|
|
89
|
+
if (['true', 'false', 'null'].includes(_value)) {
|
|
90
|
+
type = 'json';
|
|
91
|
+
value = JSON.parse(_value);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
isJsonfiable = isJsonfiable && type === 'json';
|
|
95
|
+
params.set(json, name, value);
|
|
96
|
+
}
|
|
97
|
+
if (getIsJsonfiable) return [json, isJsonfiable];
|
|
98
|
+
return json;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function renderCookieObj(cookieObj) {
|
|
102
|
+
const attrsArr = [`${cookieObj.name}=${/*encodeURIComponent*/(cookieObj.value)}`];
|
|
103
|
+
for (const attrName in cookieObj) {
|
|
104
|
+
if (['name', 'value'].includes(attrName)) continue;
|
|
105
|
+
let _attrName = attrName[0].toUpperCase() + attrName.substring(1);
|
|
106
|
+
if (_attrName === 'MaxAge') { _attrName = 'Max-Age' };
|
|
107
|
+
attrsArr.push(cookieObj[attrName] === true ? _attrName : `${_attrName}=${cookieObj[attrName]}`);
|
|
108
|
+
}
|
|
109
|
+
return attrsArr.join(';');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* Request */
|
|
113
|
+
|
|
114
|
+
Object.defineProperties(Request, {
|
|
115
|
+
create: {
|
|
116
|
+
value: function (url, init = {}) {
|
|
117
|
+
if (url instanceof Request) return url;
|
|
118
|
+
let $$type, $$body = init.body;
|
|
119
|
+
if ('body' in init) {
|
|
120
|
+
const { body, headers, $type } = renderHttpMessageInit(init);
|
|
121
|
+
init = { ...init, body, headers };
|
|
122
|
+
$$type = $type;
|
|
123
|
+
}
|
|
124
|
+
const instance = new Request(url, init);
|
|
125
|
+
instance.meta.body = $$body;
|
|
126
|
+
instance.meta.type = $$type;
|
|
127
|
+
return instance;
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
copy: {
|
|
132
|
+
value: async function (request, init = {}) {
|
|
133
|
+
const requestInit = [
|
|
134
|
+
'method', 'headers', 'mode', 'credentials', 'cache', 'redirect', 'referrer', 'integrity',
|
|
135
|
+
].reduce((init, prop) => ({ [prop]: request[prop], ...init }), {});
|
|
136
|
+
if (!['GET', 'HEAD'].includes(init.method?.toUpperCase() || request.method)) {
|
|
137
|
+
requestInit.body = await request.clone().arrayBuffer();
|
|
138
|
+
}
|
|
139
|
+
if (requestInit.mode === 'navigate') {
|
|
140
|
+
requestInit.mode = 'cors';
|
|
141
|
+
}
|
|
142
|
+
return { url: request.url, ...requestInit };
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
Object.defineProperties(Request.prototype, {
|
|
148
|
+
parse: { value: function() { return parseHttpMessage(this); } },
|
|
149
|
+
meta: { get: function() { if (!this._meta) this._meta = {}; return this._meta; } }
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
/* Response */
|
|
153
|
+
|
|
154
|
+
Object.defineProperties(Response, {
|
|
155
|
+
create: {
|
|
156
|
+
value: function (body, init = {}) {
|
|
157
|
+
if (body instanceof Response) return body;
|
|
158
|
+
let $type, $body = body;
|
|
159
|
+
if (body || body === 0) {
|
|
160
|
+
let headers;
|
|
161
|
+
({ body, headers, $type } = renderHttpMessageInit({ body, headers: init.headers }));
|
|
162
|
+
init = { ...init, headers };
|
|
163
|
+
}
|
|
164
|
+
const instance = new Response(body, init);
|
|
165
|
+
instance.meta.body = $body;
|
|
166
|
+
instance.meta.type = $type;
|
|
167
|
+
return instance;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
const statusGet = Object.getOwnPropertyDescriptor(Response.prototype, 'status');
|
|
173
|
+
Object.defineProperties(Response.prototype, {
|
|
174
|
+
parse: { value: function() { return parseHttpMessage(this); } },
|
|
175
|
+
meta: { get: function() { if (!this._meta) this._meta = {}; return this._meta; } },
|
|
176
|
+
status: { get: function() { return this.meta.status || statusGet.get.call(this); } }
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
/* Headers */
|
|
180
|
+
|
|
181
|
+
const { set: headerSet, append: headerAppend, get: headerGet } = Headers.prototype;
|
|
182
|
+
Object.defineProperties(Headers.prototype, {
|
|
183
|
+
set: {
|
|
184
|
+
value: function (name, value) {
|
|
185
|
+
// -------------------------
|
|
186
|
+
// Format "Set-Cookie" response header
|
|
187
|
+
if (/^Set-Cookie$/i.test(name) && _isObject(value)) {
|
|
188
|
+
value = renderCookieObj(value);
|
|
189
|
+
}
|
|
190
|
+
// -------------------------
|
|
191
|
+
// Format "Cookie" request header
|
|
192
|
+
if (/Cookie/i.test(name) && _isTypeObject(value)) {
|
|
193
|
+
value = [].concat(value).map(renderCookieObj).join(';');
|
|
194
|
+
}
|
|
195
|
+
// -------------------------
|
|
196
|
+
// Format "Content-Range" response header?
|
|
197
|
+
if (/^Content-Range$/i.test(name) && Array.isArray(value)) {
|
|
198
|
+
if (value.length < 2 || !value[0].includes('-')) {
|
|
199
|
+
throw new Error(`A Content-Range array must be in the format: [ 'start-end', 'total' ]`);
|
|
200
|
+
}
|
|
201
|
+
value = `bytes ${value.join('/')}`;
|
|
202
|
+
}
|
|
203
|
+
// -------------------------
|
|
204
|
+
// Format "Range" request header?
|
|
205
|
+
if (/^Range$/i.test(name)) {
|
|
206
|
+
let rangeArr = [];
|
|
207
|
+
_arrFrom(value).forEach((range, i) => {
|
|
208
|
+
let rangeStr = Array.isArray(range) ? range.join('-') : range + '';
|
|
209
|
+
if (i === 0 && !rangeStr.includes('bytes=')) {
|
|
210
|
+
rangeStr = `bytes=${rangeStr}`;
|
|
211
|
+
}
|
|
212
|
+
rangeArr.push(rangeStr);
|
|
213
|
+
});
|
|
214
|
+
value = rangeArr.join(', ');
|
|
215
|
+
}
|
|
216
|
+
// -------------------------
|
|
217
|
+
// Format "Accept" request header?
|
|
218
|
+
if (/^Accept$/i.test(name) && Array.isArray(value)) {
|
|
219
|
+
value = value.join(',');
|
|
220
|
+
}
|
|
221
|
+
// -------------------------
|
|
222
|
+
return headerSet.call(this, name, value);
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
|
|
226
|
+
append: {
|
|
227
|
+
value: function (name, value) {
|
|
228
|
+
// -------------------------
|
|
229
|
+
// Format "Set-Cookie" response header
|
|
230
|
+
if (/^Set-Cookie$/i.test(name) && _isObject(value)) {
|
|
231
|
+
value = renderCookieObj(value);
|
|
232
|
+
}
|
|
233
|
+
// -------------------------
|
|
234
|
+
return headerAppend.call(this, name, value);
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
|
|
238
|
+
get: {
|
|
239
|
+
value: function (name, parsed = false) {
|
|
240
|
+
let value = headerGet.call(this, name);
|
|
241
|
+
// -------------------------
|
|
242
|
+
// Parse "Set-Cookie" response header
|
|
243
|
+
if (/^Set-Cookie$/i.test(name) && parsed) {
|
|
244
|
+
value = this.getSetCookie()/*IMPORTANT*/.map((str) => {
|
|
245
|
+
const [cookieDefinition, attrsStr] = str.split(';');
|
|
246
|
+
const [name, value] = cookieDefinition.split('=').map((s) => s.trim());
|
|
247
|
+
const cookieObj = { name, value: /*decodeURIComponent*/(value), };
|
|
248
|
+
attrsStr && attrsStr.split(/\;/g).map(attrStr => attrStr.trim().split('=')).forEach(attrsArr => {
|
|
249
|
+
cookieObj[attrsArr[0][0].toLowerCase() + attrsArr[0].substring(1).replace('-', '')] = attrsArr.length === 1 ? true : attrsArr[1];
|
|
250
|
+
});
|
|
251
|
+
return cookieObj;
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
// -------------------------
|
|
255
|
+
// Parse "Cookie" request header
|
|
256
|
+
if (/^Cookie$/i.test(name) && parsed) {
|
|
257
|
+
value = value?.split(';').map((str) => {
|
|
258
|
+
const [name, value] = str.split('=').map((s) => s.trim());
|
|
259
|
+
return { name, value: /*decodeURIComponent*/(value), };
|
|
260
|
+
}) || [];
|
|
261
|
+
}
|
|
262
|
+
// -------------------------
|
|
263
|
+
// Parse "Content-Range" response header?
|
|
264
|
+
if (/^Content-Range$/i.test(name) && value && parsed) {
|
|
265
|
+
value = _after(value, 'bytes ').split('/');
|
|
266
|
+
}
|
|
267
|
+
// -------------------------
|
|
268
|
+
// Parse "Range" request header?
|
|
269
|
+
if (/^Range$/i.test(name) && parsed) {
|
|
270
|
+
value = !value ? [] : _after(value, 'bytes=').split(',').map((rangeStr) => {
|
|
271
|
+
let range = rangeStr.trim().split('-');
|
|
272
|
+
range[0] = range[0] ? parseInt(range[0], 10) : undefined;
|
|
273
|
+
if (range[1]) {
|
|
274
|
+
range[1] = parseInt(range[1], 10);
|
|
275
|
+
}
|
|
276
|
+
range.clamp = max => {
|
|
277
|
+
if (range[1] > max - 1 || range[1] === undefined) {
|
|
278
|
+
range[1] = max - 1;
|
|
279
|
+
}
|
|
280
|
+
if (range[0] === undefined) range[0] = range[1] ? max - range[1] - 1 : 0;
|
|
281
|
+
};
|
|
282
|
+
return range;
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
// -------------------------
|
|
286
|
+
// Parse "Accept" request header?
|
|
287
|
+
if (/^Accept$/i.test(name) && parsed) {
|
|
288
|
+
const list = value && value.split(',')
|
|
289
|
+
.map((a) => (a = a.trim().split(';').map(a => a.trim()), [a.shift(), parseFloat((a.pop() || '1').replace('q=', ''))]))
|
|
290
|
+
.sort((a, b) => a[1] > b[1] ? -1 : 1) || [];
|
|
291
|
+
value = {
|
|
292
|
+
match(mime) {
|
|
293
|
+
mime = (mime + '').split('/');
|
|
294
|
+
return list.reduce((prev, entry) => prev || (
|
|
295
|
+
(entry = entry[0].split('/')) && [0, 1].every(i => ((mime[i] === entry[i]) || mime[i] === '*' || entry[i] === '*'))
|
|
296
|
+
), false);
|
|
297
|
+
},
|
|
298
|
+
toString() {
|
|
299
|
+
return value;
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
// -------------------------
|
|
304
|
+
return value;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
/* FormData */
|
|
310
|
+
|
|
311
|
+
Object.defineProperties(FormData, {
|
|
312
|
+
json: { value: createFormDataFromJson }
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
Object.defineProperties(FormData.prototype, {
|
|
316
|
+
json: {
|
|
317
|
+
value: async function (data = {}) {
|
|
318
|
+
const result = await renderFormDataToJson(this, ...arguments);
|
|
319
|
+
return result;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
});
|