@webqit/webflo 0.8.72-0 → 0.8.72
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/package.json
CHANGED
|
@@ -106,21 +106,25 @@ const _MessageStream = (NativeMessageStream, Headers, FormData) => {
|
|
|
106
106
|
// Payload
|
|
107
107
|
data(force = false) {
|
|
108
108
|
if (!this._typedDataCache.data || force) {
|
|
109
|
-
this._typedDataCache.data = new Promise(async resolve => {
|
|
110
|
-
var
|
|
109
|
+
this._typedDataCache.data = new Promise(async (resolve, reject) => {
|
|
110
|
+
var messageInstance = this, data, contentType = messageInstance.headers.get('content-type') || '';
|
|
111
111
|
var type = contentType === 'application/json' || this._typedDataCache.json ? 'json' : (
|
|
112
|
-
contentType === 'application/x-www-form-urlencoded' || contentType.startsWith('multipart/') || this._typedDataCache.formData
|
|
112
|
+
contentType === 'application/x-www-form-urlencoded' || contentType.startsWith('multipart/') || this._typedDataCache.formData ? 'formData' : (
|
|
113
113
|
contentType === 'text/plain' ? 'plain' : 'other'
|
|
114
114
|
)
|
|
115
115
|
);
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
type === '
|
|
121
|
-
|
|
116
|
+
try {
|
|
117
|
+
if (type === 'formData') {
|
|
118
|
+
data = (await messageInstance.formData()).json();
|
|
119
|
+
} else {
|
|
120
|
+
data = type === 'json' ? await messageInstance.json() : (
|
|
121
|
+
type === 'plain' ? await messageInstance.text() : messageInstance.body
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
resolve(data);
|
|
125
|
+
} catch(e) {
|
|
126
|
+
reject(e);
|
|
122
127
|
}
|
|
123
|
-
resolve(data);
|
|
124
128
|
});
|
|
125
129
|
}
|
|
126
130
|
return this._typedDataCache.data;
|
|
@@ -69,6 +69,14 @@ const _ResponseHeaders = NativeHeaders => class extends _Headers(NativeHeaders)
|
|
|
69
69
|
return value;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
get location() {
|
|
73
|
+
return this.get('Location');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
set location(value) {
|
|
77
|
+
return this.set('Location', value);
|
|
78
|
+
}
|
|
79
|
+
|
|
72
80
|
get redirect() {
|
|
73
81
|
return this.get('Location');
|
|
74
82
|
}
|
|
@@ -76,6 +84,7 @@ const _ResponseHeaders = NativeHeaders => class extends _Headers(NativeHeaders)
|
|
|
76
84
|
set redirect(value) {
|
|
77
85
|
return this.set('Location', value);
|
|
78
86
|
}
|
|
87
|
+
|
|
79
88
|
}
|
|
80
89
|
|
|
81
90
|
export default _ResponseHeaders;
|
|
@@ -39,25 +39,97 @@ export default class Http {
|
|
|
39
39
|
/**
|
|
40
40
|
* Performs a request.
|
|
41
41
|
*
|
|
42
|
-
* @param string href
|
|
43
|
-
* @param object
|
|
44
|
-
* @param object src
|
|
42
|
+
* @param object|string href
|
|
43
|
+
* @param object options
|
|
45
44
|
*
|
|
46
|
-
* @return
|
|
45
|
+
* @return void
|
|
47
46
|
*/
|
|
48
|
-
go(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
47
|
+
async go(url, options = {}) {
|
|
48
|
+
if (this.activeController) {
|
|
49
|
+
this.activeController.abort();
|
|
50
|
+
}
|
|
51
|
+
this.activeController = new AbortController();
|
|
52
|
+
// Generates request object
|
|
53
|
+
let generateRequest = (url, options) => {
|
|
54
|
+
return new StdRequest(url, {
|
|
55
|
+
...options,
|
|
56
|
+
headers: {
|
|
57
|
+
'Accept': 'application/json',
|
|
58
|
+
'X-No-Cors-Redirect': 'manual',
|
|
59
|
+
'X-Powered-By': '@webqit/webflo',
|
|
60
|
+
...(options.headers || {}),
|
|
61
|
+
},
|
|
62
|
+
referrer: window.document.location.href,
|
|
63
|
+
signal: this.activeController.signal,
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
// Handles response object
|
|
67
|
+
let handleResponse = (response) => {
|
|
68
|
+
if (!response) return;
|
|
69
|
+
if (response.redirected && this.isSameOrigin(response.url)) {
|
|
70
|
+
Observer.set(this.location, { href: response.url }, {
|
|
71
|
+
detail: { isRedirect: true },
|
|
72
|
+
});
|
|
73
|
+
} else if (response.headers.get('X-No-Cors-Redirect')) {
|
|
74
|
+
window.location = response.headers.get('Location');
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
url = typeof url === 'string' ? { href: url } : url;
|
|
78
|
+
options = { referrer: window.document.location.href, ...options };
|
|
79
|
+
Observer.set(this.location, url, { detail: options, });
|
|
80
|
+
if (options.srcType === 'history' || !(_before(url.href, '#') === _before(options.referrer, '#') && (options.method || 'GET').toUpperCase() === 'GET')) {
|
|
81
|
+
handleResponse(await client.call(this, generateRequest(url.href, options)));
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Checks if an URL is same origin.
|
|
87
|
+
*
|
|
88
|
+
* @param object|string url
|
|
89
|
+
*
|
|
90
|
+
* @return Bool
|
|
91
|
+
*/
|
|
92
|
+
isSameOrigin(url) {
|
|
93
|
+
if (typeof url === 'string') {
|
|
94
|
+
let href = url;
|
|
95
|
+
url = window.document.createElement('a');
|
|
96
|
+
url.href = href
|
|
97
|
+
}
|
|
98
|
+
return !url.origin || url.origin === this.location.origin;
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* History object
|
|
103
|
+
*/
|
|
104
|
+
get history() {
|
|
105
|
+
return window.history;
|
|
52
106
|
}
|
|
107
|
+
|
|
53
108
|
};
|
|
54
109
|
|
|
110
|
+
// -----------------------
|
|
111
|
+
// Initialize instance
|
|
112
|
+
Observer.set(instance, 'location', new Url(window.document.location));
|
|
113
|
+
// -----------------------
|
|
114
|
+
// Syndicate changes to the browser;s location bar
|
|
115
|
+
Observer.observe(instance.location, [[ 'href' ]], ([e]) => {
|
|
116
|
+
if (e.value === 'http:' || (e.detail || {}).src === window.document.location) {
|
|
117
|
+
// Already from a "popstate" event as above, so don't push again
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (e.value === window.document.location.href || e.value + '/' === window.document.location.href) {
|
|
121
|
+
instance.history.replaceState(instance.history.state, '', instance.location.href);
|
|
122
|
+
} else {
|
|
123
|
+
try { instance.history.pushState(instance.history.state, '', instance.location.href); } catch(e) {}
|
|
124
|
+
}
|
|
125
|
+
}, { diff: true });
|
|
126
|
+
|
|
55
127
|
/**
|
|
56
128
|
* ----------------
|
|
57
|
-
*
|
|
129
|
+
* Navigation Interception
|
|
58
130
|
* ----------------
|
|
59
131
|
*/
|
|
60
|
-
|
|
132
|
+
|
|
61
133
|
// -----------------------
|
|
62
134
|
// This event is triggered by
|
|
63
135
|
// either the browser back button,
|
|
@@ -67,10 +139,9 @@ export default class Http {
|
|
|
67
139
|
window.addEventListener('popstate', e => {
|
|
68
140
|
// Needed to allow window.document.location
|
|
69
141
|
// to update to window.location
|
|
142
|
+
let referrer = window.document.location.href;
|
|
70
143
|
window.setTimeout(() => {
|
|
71
|
-
|
|
72
|
-
detail: { type: 'history', src: window.document.location },
|
|
73
|
-
});
|
|
144
|
+
instance.go(Url.copy(window.document.location), { referrer, src: window.document.location, srcType: 'history', });
|
|
74
145
|
}, 0);
|
|
75
146
|
});
|
|
76
147
|
|
|
@@ -78,24 +149,17 @@ export default class Http {
|
|
|
78
149
|
// Capture all link-clicks
|
|
79
150
|
// and fire to this router.
|
|
80
151
|
window.addEventListener('click', e => {
|
|
81
|
-
var anchor
|
|
82
|
-
if (
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
// Same origin... but...
|
|
86
|
-
&& (!anchor.origin || anchor.origin === instance.location.origin)) {
|
|
87
|
-
if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
152
|
+
var anchor = e.target.closest('a');
|
|
153
|
+
if (!anchor || !anchor.href) return;
|
|
154
|
+
if (!anchor.target && !anchor.download && (!anchor.origin || anchor.origin === instance.location.origin)) {
|
|
155
|
+
if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return;
|
|
90
156
|
// Publish everything, including hash
|
|
91
|
-
|
|
92
|
-
detail: { type: 'link', src: anchor, },
|
|
93
|
-
});
|
|
157
|
+
instance.go(Url.copy(anchor), { src: anchor, srcType: 'link', });
|
|
94
158
|
// URLs with # will cause a natural navigation
|
|
95
159
|
// even if pointing to a different page, a natural navigation will still happen
|
|
96
160
|
// because with the Observer.set() above, window.document.location.href would have become
|
|
97
161
|
// the destination page, which makes it look like same page navigation
|
|
98
|
-
if (!href.includes('#')) {
|
|
162
|
+
if (!anchor.href.includes('#')) {
|
|
99
163
|
e.preventDefault();
|
|
100
164
|
}
|
|
101
165
|
}
|
|
@@ -105,25 +169,27 @@ export default class Http {
|
|
|
105
169
|
// Capture all form-submit
|
|
106
170
|
// and fire to this router.
|
|
107
171
|
window.addEventListener('submit', e => {
|
|
108
|
-
var
|
|
109
|
-
form = e.target.closest('form'),
|
|
172
|
+
var form = e.target.closest('form'),
|
|
110
173
|
submits = [e.submitter]; //_arrFrom(form.elements).filter(el => el.matches('button,input[type="submit"],input[type="image"]'));
|
|
111
174
|
var submitParams = [ 'action', 'enctype', 'method', 'noValidate', 'target' ].reduce((params, prop) => {
|
|
112
175
|
params[prop] = submits.reduce((val, el) => val || (el.hasAttribute(`form${prop.toLowerCase()}`) ? el[`form${_toTitle(prop)}`] : null), null) || form[prop];
|
|
113
176
|
return params;
|
|
114
177
|
}, {});
|
|
115
178
|
// We support method hacking
|
|
116
|
-
// ---------------
|
|
117
179
|
submitParams.method = e.submitter.dataset.method || form.dataset.method || submitParams.method;
|
|
118
180
|
// ---------------
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
181
|
+
var actionEl = window.document.createElement('a');
|
|
182
|
+
actionEl.href = submitParams.action;
|
|
183
|
+
// ---------------
|
|
184
|
+
// If not targeted and same origin...
|
|
185
|
+
if (!submitParams.target && (!actionEl.origin || actionEl.origin === instance.location.origin)) {
|
|
186
|
+
if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) return;
|
|
187
|
+
// Build data
|
|
122
188
|
var formData = new FormData(form);
|
|
123
189
|
if (e.submitter.name) {
|
|
124
190
|
formData.set(e.submitter.name, e.submitter.value);
|
|
125
191
|
}
|
|
126
|
-
if (submitParams.method === '
|
|
192
|
+
if (submitParams.method.toUpperCase() === 'GET') {
|
|
127
193
|
var query = wwwFormUnserialize(actionEl.search);
|
|
128
194
|
Array.from(formData.entries()).forEach(_entry => {
|
|
129
195
|
wwwFormSet(query, _entry[0], _entry[1], false);
|
|
@@ -131,13 +197,7 @@ export default class Http {
|
|
|
131
197
|
actionEl.search = wwwFormSerialize(query);
|
|
132
198
|
formData = null;
|
|
133
199
|
}
|
|
134
|
-
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
// Publish everything, including hash
|
|
138
|
-
Observer.set(instance.location, Url.copy(actionEl), {
|
|
139
|
-
detail: { type: 'form', src: form, submitParams, data: formData },
|
|
140
|
-
});
|
|
200
|
+
instance.go(Url.copy(actionEl), { ...submitParams, body: formData, src: form, srcType: 'form', });
|
|
141
201
|
// URLs with # will cause a natural navigation
|
|
142
202
|
// even if pointing to a different page, a natural navigation will still happen
|
|
143
203
|
// because with the Observer.set() above, window.document.location.href would have become
|
|
@@ -148,71 +208,9 @@ export default class Http {
|
|
|
148
208
|
}
|
|
149
209
|
});
|
|
150
210
|
|
|
151
|
-
/**
|
|
152
|
-
* ----------------
|
|
153
|
-
* instance.history
|
|
154
|
-
* ----------------
|
|
155
|
-
*/
|
|
156
|
-
|
|
157
|
-
instance.history = window.history;
|
|
158
211
|
// -----------------------
|
|
159
|
-
// Syndicate changes to
|
|
160
|
-
// the browser;s location bar
|
|
161
|
-
Observer.observe(instance.location, [[ 'href' ]], e => {
|
|
162
|
-
e = e[0];
|
|
163
|
-
if ((e.detail || {}).src === window.document.location) {
|
|
164
|
-
// Already from a "popstate" event as above, so don't push again
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
if (e.value === 'http:') return;
|
|
168
|
-
if (e.value === window.document.location.href || e.value + '/' === window.document.location.href) {
|
|
169
|
-
instance.history.replaceState(instance.history.state, '', instance.location.href);
|
|
170
|
-
} else {
|
|
171
|
-
try {
|
|
172
|
-
instance.history.pushState(instance.history.state, '', instance.location.href);
|
|
173
|
-
} catch(e) {}
|
|
174
|
-
}
|
|
175
|
-
}, { diff: true });
|
|
176
|
-
|
|
177
|
-
// ----------------------------------
|
|
178
|
-
const createRequest = (url, referrer, e = {}) => {
|
|
179
|
-
var detail = e.detail || {};
|
|
180
|
-
var options = {
|
|
181
|
-
method: (detail.submitParams || detail.src || {}).method || 'get',
|
|
182
|
-
body: detail.data,
|
|
183
|
-
headers: { ...(detail.headers || {}), 'X-Powered-By': '@webqit/webflo', },
|
|
184
|
-
referrer,
|
|
185
|
-
};
|
|
186
|
-
return new StdRequest(url, options);
|
|
187
|
-
};
|
|
188
|
-
const handleResponse = response => {
|
|
189
|
-
if (response && response.redirected) {
|
|
190
|
-
window.location = response.url;
|
|
191
|
-
return;
|
|
192
|
-
var actionEl = window.document.createElement('a');
|
|
193
|
-
if ((actionEl.href = response.url) && (!actionEl.origin || actionEl.origin === instance.location.origin)) {
|
|
194
|
-
Observer.set(instance.location, { href: response.url }, {
|
|
195
|
-
detail: { follow: false },
|
|
196
|
-
});
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
// ----------------------------------
|
|
201
|
-
|
|
202
|
-
// Observe location and route
|
|
203
|
-
Observer.observe(instance.location, [['href']], async e => {
|
|
204
|
-
e = e[0];
|
|
205
|
-
var detail = e.detail || {};
|
|
206
|
-
if (detail.follow === false) return;
|
|
207
|
-
var method = (detail.submitParams || detail.src || {}).method;
|
|
208
|
-
if ((_before(e.value, '#') !== _before(e.oldValue, '#')) || (method && method.toUpperCase() !== 'GET')) {
|
|
209
|
-
return handleResponse(await client.call(instance, createRequest(e.value, e.oldValue, e), e));
|
|
210
|
-
}
|
|
211
|
-
}, {diff: false /* method might be the difference */});
|
|
212
212
|
// Startup route
|
|
213
|
-
|
|
214
|
-
handleResponse(await client.call(instance, createRequest(window.document.location.href, document.referrer)));
|
|
215
|
-
|
|
213
|
+
instance.go(window.document.location.href, { referrer: document.referrer });
|
|
216
214
|
return instance;
|
|
217
215
|
}
|
|
218
216
|
|
|
@@ -74,50 +74,39 @@ export default function(layout, params) {
|
|
|
74
74
|
// -----------------
|
|
75
75
|
var networkProgress = networkProgressOngoing = new RequestHandle();
|
|
76
76
|
networkProgress.setActive(true, event.request._method || event.request.method);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
// Sync session data to cache to be available to service-worker routers
|
|
87
|
-
const response = fetch(event.request, {}, networkProgress.updateProgress.bind(networkProgress));
|
|
88
|
-
// -----------------
|
|
89
|
-
// -----------------
|
|
90
|
-
response.catch(e => networkProgress.throw(e.message));
|
|
91
|
-
return response.then(async _response => {
|
|
92
|
-
_response = new clientNavigationEvent.Response(_response.body, {
|
|
93
|
-
status: _response.status,
|
|
94
|
-
statusText: _response.statusText,
|
|
95
|
-
headers: _response.headers,
|
|
77
|
+
const _response = fetch(event.request);
|
|
78
|
+
// This catch() is NOT intended to handle failure of the fetch
|
|
79
|
+
_response.catch(e => networkProgress.throw(e.message));
|
|
80
|
+
// Save a reference to this
|
|
81
|
+
return _response.then(async response => {
|
|
82
|
+
response = new clientNavigationEvent.Response(response.body, {
|
|
83
|
+
status: response.status,
|
|
84
|
+
statusText: response.statusText,
|
|
85
|
+
headers: response.headers,
|
|
96
86
|
_proxy: {
|
|
97
|
-
url:
|
|
98
|
-
ok:
|
|
99
|
-
redirected:
|
|
87
|
+
url: response.url,
|
|
88
|
+
ok: response.ok,
|
|
89
|
+
redirected: response.redirected
|
|
100
90
|
},
|
|
101
91
|
});
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
// Return a promise that never resolves as a new response is underway
|
|
105
|
-
if (!networkProgress.active) {
|
|
106
|
-
return new Promise(() => {});
|
|
92
|
+
if (response.headers.get('Location')) {
|
|
93
|
+
networkProgress.redirecting(response.headers.get('Location'));
|
|
107
94
|
}
|
|
108
95
|
// Stop loading status
|
|
109
96
|
networkProgress.setActive(false);
|
|
110
|
-
return
|
|
97
|
+
return response;
|
|
111
98
|
});
|
|
112
99
|
});
|
|
113
100
|
if ($context.response instanceof clientNavigationEvent.Response) {
|
|
114
|
-
|
|
115
|
-
}
|
|
101
|
+
$context.data = await $context.response.data();
|
|
102
|
+
} else {
|
|
103
|
+
$context.data = $context.response;
|
|
104
|
+
}
|
|
116
105
|
|
|
117
106
|
// --------
|
|
118
107
|
// Render
|
|
119
108
|
// --------
|
|
120
|
-
const rendering = await router.route('render', clientNavigationEvent, $context.
|
|
109
|
+
const rendering = await router.route('render', clientNavigationEvent, $context.data, async function(event, data) {
|
|
121
110
|
// --------
|
|
122
111
|
// OOHTML would waiting for DOM-ready in order to be initialized
|
|
123
112
|
await new Promise(res => window.WebQit.DOM.ready(res));
|
|
@@ -168,7 +157,7 @@ export default function(layout, params) {
|
|
|
168
157
|
|
|
169
158
|
}
|
|
170
159
|
|
|
171
|
-
return $context.
|
|
160
|
+
return $context.response;
|
|
172
161
|
});
|
|
173
162
|
|
|
174
163
|
};
|
|
@@ -202,6 +191,9 @@ class RequestHandle {
|
|
|
202
191
|
valuetotal,
|
|
203
192
|
});
|
|
204
193
|
}
|
|
194
|
+
redirecting(location) {
|
|
195
|
+
Observer.set(networkWatch, 'redirecting', location);
|
|
196
|
+
}
|
|
205
197
|
throw(message) {
|
|
206
198
|
if (this.active === false) {
|
|
207
199
|
return;
|
|
@@ -117,7 +117,7 @@ export default function(layout, params) {
|
|
|
117
117
|
}
|
|
118
118
|
return _response;
|
|
119
119
|
}
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
return defaultFetch(evt);
|
|
122
122
|
};
|
|
123
123
|
evt.respondWith(handleFetch(evt));
|
|
@@ -144,13 +144,12 @@ export default function(layout, params) {
|
|
|
144
144
|
return network_fetch(evt);
|
|
145
145
|
};
|
|
146
146
|
|
|
147
|
-
//evt.request.mode navigate evt.request.cache force-cache evt.request.destination document request.headers.get('Accept') text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
|
|
148
147
|
//evt.request.mode navigate evt.request.cache force-cache evt.request.destination document request.headers.get('Accept') text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
|
|
149
148
|
|
|
150
149
|
const getCacheName = request => request.headers.get('Accept') === 'application/json'
|
|
151
150
|
? params.cache_name + '_json'
|
|
152
151
|
: params.cache_name;
|
|
153
|
-
|
|
152
|
+
|
|
154
153
|
// Caching strategy: cache_first
|
|
155
154
|
const cache_fetch = (evt, cacheRefresh = false, is_Navigate_ForceCache_Document = false) => {
|
|
156
155
|
|
|
@@ -162,10 +161,10 @@ export default function(layout, params) {
|
|
|
162
161
|
let url = new URL(request.url);
|
|
163
162
|
url.searchParams.set('$force-cache', '1');
|
|
164
163
|
request = new Request(url, {
|
|
165
|
-
method: request.method,
|
|
164
|
+
method: request.method,
|
|
166
165
|
headers: request.headers,
|
|
167
166
|
body: request.body,
|
|
168
|
-
mode: request.mode === 'navigate' ? null : request.mode,
|
|
167
|
+
mode: request.mode === 'navigate'/* throws */ ? null : request.mode,
|
|
169
168
|
credentials: request.credentials,
|
|
170
169
|
cache: request.cache,
|
|
171
170
|
redirect: request.redirect,
|
|
@@ -17,7 +17,6 @@ import _isArray from '@webqit/util/js/isArray.js';
|
|
|
17
17
|
import { _isString, _isPlainObject, _isPlainArray } from '@webqit/util/js/index.js';
|
|
18
18
|
import _delay from '@webqit/util/js/delay.js';
|
|
19
19
|
import { slice as _streamSlice } from 'stream-slice';
|
|
20
|
-
import { v4 as uuidv4, v5 as uuidv5 } from 'uuid';
|
|
21
20
|
import * as config from '../../config/index.js';
|
|
22
21
|
import * as services from '../../services/index.js';
|
|
23
22
|
import NavigationEvent from './NavigationEvent.js';
|
|
@@ -408,12 +407,7 @@ export async function run(hostSetup, request, response, Ui, flags = {}, protocol
|
|
|
408
407
|
// -------------------
|
|
409
408
|
// Chrome needs this for audio elements to play
|
|
410
409
|
response.setHeader('Accept-Ranges', 'bytes');
|
|
411
|
-
/*
|
|
412
|
-
if ($context.response.headers.contentLength && !$context.response.headers.contentRange) {
|
|
413
|
-
$context.response.headers.contentRange = `bytes 0-${$context.response.headers.contentLength}/${$context.response.headers.contentLength}`;
|
|
414
|
-
}
|
|
415
410
|
|
|
416
|
-
*/
|
|
417
411
|
// -------------------
|
|
418
412
|
// Automatic response headers
|
|
419
413
|
// -------------------
|
|
@@ -470,8 +464,15 @@ export async function run(hostSetup, request, response, Ui, flags = {}, protocol
|
|
|
470
464
|
// Send
|
|
471
465
|
// -------------------
|
|
472
466
|
if ($context.response.headers.redirect) {
|
|
473
|
-
|
|
474
|
-
response.
|
|
467
|
+
if (serverNavigationEvent.request.headers.get('X-No-Cors-Redirect') === 'manual'
|
|
468
|
+
&& (new serverNavigationEvent.globals.URL($context.response.headers.location)).origin !== serverNavigationEvent.url.origin) {
|
|
469
|
+
response.statusCode = 200;
|
|
470
|
+
response.setHeader('X-No-Cors-Redirect', $context.response.status);
|
|
471
|
+
response.end();
|
|
472
|
+
} else {
|
|
473
|
+
response.statusCode = $context.response.status;
|
|
474
|
+
response.end();
|
|
475
|
+
}
|
|
475
476
|
} else if ($context.response.original !== undefined && $context.response.original !== null) {
|
|
476
477
|
response.statusCode = $context.response.status;
|
|
477
478
|
response.statusMessage = $context.response.statusText;
|
|
@@ -551,15 +552,23 @@ export async function run(hostSetup, request, response, Ui, flags = {}, protocol
|
|
|
551
552
|
// --------
|
|
552
553
|
|
|
553
554
|
if (flags.logs !== false) {
|
|
555
|
+
let errorCode = [ 404, 500 ].includes(response.statusCode) ? response.statusCode : 0;
|
|
556
|
+
let noCorsRedirect = response.getHeader('X-No-Cors-Redirect');
|
|
557
|
+
let redirectCode = noCorsRedirect || ((response.statusCode + '').startsWith('3') ? response.statusCode : 0);
|
|
558
|
+
let statusCode = noCorsRedirect || response.statusCode;
|
|
554
559
|
Ui.log(''
|
|
555
560
|
+ '[' + (hostSetup.vh ? Ui.style.keyword(hostSetup.vh.host) + '][' : '') + Ui.style.comment((new Date).toUTCString()) + '] '
|
|
556
561
|
+ Ui.style.keyword(protocol.toUpperCase() + ' ' + serverNavigationEvent.request.method) + ' '
|
|
557
562
|
+ Ui.style.url(serverNavigationEvent.request.url) + ($context.response && ($context.response.meta || {}).autoIndex ? Ui.style.comment((!serverNavigationEvent.request.url.endsWith('/') ? '/' : '') + $context.response.meta.autoIndex) : '') + ' '
|
|
558
563
|
+ (' (' + Ui.style.comment($context.response && ($context.response.headers || {}).contentType ? $context.response.headers.contentType : 'unknown') + ') ')
|
|
559
564
|
+ (
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
565
|
+
errorCode
|
|
566
|
+
? Ui.style.err(errorCode + ($context.fatal ? ` [ERROR]: ${$context.fatal.error || $context.fatal.toString()}` : ``))
|
|
567
|
+
: Ui.style.val(statusCode) + (
|
|
568
|
+
redirectCode
|
|
569
|
+
? ' - ' + Ui.style.val(response.getHeader('Location'))
|
|
570
|
+
: ' (' + Ui.style.keyword(response.getHeader('Content-Range') || response.statusMessage) + ')'
|
|
571
|
+
)
|
|
563
572
|
)
|
|
564
573
|
);
|
|
565
574
|
}
|