@sveltejs/kit 1.0.0-next.509 → 1.0.0-next.510
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 +1 -1
- package/src/runtime/server/cookie.js +48 -9
- package/src/runtime/server/{page/fetch.js → fetch.js} +17 -144
- package/src/runtime/server/index.js +7 -3
- package/src/runtime/server/page/index.js +13 -16
- package/src/runtime/server/page/load_data.js +102 -3
- package/src/runtime/server/page/render.js +0 -5
- package/src/runtime/server/page/respond_with_error.js +9 -13
- package/src/runtime/server/page/types.d.ts +0 -6
- package/src/runtime/server/utils.js +1 -4
- package/types/index.d.ts +1 -0
package/package.json
CHANGED
|
@@ -5,8 +5,12 @@ import { parse, serialize } from 'cookie';
|
|
|
5
5
|
* @param {URL} url
|
|
6
6
|
*/
|
|
7
7
|
export function get_cookies(request, url) {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
const header = request.headers.get('cookie') ?? '';
|
|
9
|
+
|
|
10
|
+
const initial_cookies = parse(header);
|
|
11
|
+
|
|
12
|
+
/** @type {Record<string, import('./page/types').Cookie>} */
|
|
13
|
+
const new_cookies = {};
|
|
10
14
|
|
|
11
15
|
/** @type {import('cookie').CookieSerializeOptions} */
|
|
12
16
|
const defaults = {
|
|
@@ -27,7 +31,7 @@ export function get_cookies(request, url) {
|
|
|
27
31
|
* @param {import('cookie').CookieParseOptions} opts
|
|
28
32
|
*/
|
|
29
33
|
get(name, opts) {
|
|
30
|
-
const c = new_cookies
|
|
34
|
+
const c = new_cookies[name];
|
|
31
35
|
if (
|
|
32
36
|
c &&
|
|
33
37
|
domain_matches(url.hostname, c.options.domain) &&
|
|
@@ -37,7 +41,7 @@ export function get_cookies(request, url) {
|
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
const decode = opts?.decode || decodeURIComponent;
|
|
40
|
-
const req_cookies = parse(
|
|
44
|
+
const req_cookies = parse(header, { decode });
|
|
41
45
|
return req_cookies[name]; // the decoded string or undefined
|
|
42
46
|
},
|
|
43
47
|
|
|
@@ -47,14 +51,14 @@ export function get_cookies(request, url) {
|
|
|
47
51
|
* @param {import('cookie').CookieSerializeOptions} opts
|
|
48
52
|
*/
|
|
49
53
|
set(name, value, opts = {}) {
|
|
50
|
-
new_cookies
|
|
54
|
+
new_cookies[name] = {
|
|
51
55
|
name,
|
|
52
56
|
value,
|
|
53
57
|
options: {
|
|
54
58
|
...defaults,
|
|
55
59
|
...opts
|
|
56
60
|
}
|
|
57
|
-
}
|
|
61
|
+
};
|
|
58
62
|
},
|
|
59
63
|
|
|
60
64
|
/**
|
|
@@ -62,7 +66,7 @@ export function get_cookies(request, url) {
|
|
|
62
66
|
* @param {import('cookie').CookieSerializeOptions} opts
|
|
63
67
|
*/
|
|
64
68
|
delete(name, opts = {}) {
|
|
65
|
-
new_cookies
|
|
69
|
+
new_cookies[name] = {
|
|
66
70
|
name,
|
|
67
71
|
value: '',
|
|
68
72
|
options: {
|
|
@@ -70,7 +74,7 @@ export function get_cookies(request, url) {
|
|
|
70
74
|
...opts,
|
|
71
75
|
maxAge: 0
|
|
72
76
|
}
|
|
73
|
-
}
|
|
77
|
+
};
|
|
74
78
|
},
|
|
75
79
|
|
|
76
80
|
/**
|
|
@@ -86,7 +90,42 @@ export function get_cookies(request, url) {
|
|
|
86
90
|
}
|
|
87
91
|
};
|
|
88
92
|
|
|
89
|
-
|
|
93
|
+
/**
|
|
94
|
+
* @param {URL} destination
|
|
95
|
+
* @param {string | null} header
|
|
96
|
+
*/
|
|
97
|
+
function get_cookie_header(destination, header) {
|
|
98
|
+
/** @type {Record<string, string>} */
|
|
99
|
+
const combined_cookies = {};
|
|
100
|
+
|
|
101
|
+
// cookies sent by the user agent have lowest precedence
|
|
102
|
+
for (const name in initial_cookies) {
|
|
103
|
+
combined_cookies[name] = initial_cookies[name];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// cookies previous set during this event with cookies.set have higher precedence
|
|
107
|
+
for (const key in new_cookies) {
|
|
108
|
+
const cookie = new_cookies[key];
|
|
109
|
+
if (!domain_matches(destination.hostname, cookie.options.domain)) continue;
|
|
110
|
+
if (!path_matches(destination.pathname, cookie.options.path)) continue;
|
|
111
|
+
|
|
112
|
+
combined_cookies[cookie.name] = cookie.value;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// explicit header has highest precedence
|
|
116
|
+
if (header) {
|
|
117
|
+
const parsed = parse(header);
|
|
118
|
+
for (const name in parsed) {
|
|
119
|
+
combined_cookies[name] = parsed[name];
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return Object.entries(combined_cookies)
|
|
124
|
+
.map(([name, value]) => `${name}=${value}`)
|
|
125
|
+
.join('; ');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return { cookies, new_cookies, get_cookie_header };
|
|
90
129
|
}
|
|
91
130
|
|
|
92
131
|
/**
|
|
@@ -1,58 +1,17 @@
|
|
|
1
|
-
import * as cookie from 'cookie';
|
|
2
1
|
import * as set_cookie_parser from 'set-cookie-parser';
|
|
3
|
-
import { respond } from '
|
|
4
|
-
import { domain_matches, path_matches } from '../cookie.js';
|
|
2
|
+
import { respond } from './index.js';
|
|
5
3
|
|
|
6
4
|
/**
|
|
7
5
|
* @param {{
|
|
8
6
|
* event: import('types').RequestEvent;
|
|
9
7
|
* options: import('types').SSROptions;
|
|
10
8
|
* state: import('types').SSRState;
|
|
11
|
-
*
|
|
12
|
-
* prerender_default?: import('types').PrerenderOption;
|
|
13
|
-
* resolve_opts: import('types').RequiredResolveOptions;
|
|
9
|
+
* get_cookie_header: (url: URL, header: string | null) => string;
|
|
14
10
|
* }} opts
|
|
11
|
+
* @returns {typeof fetch}
|
|
15
12
|
*/
|
|
16
|
-
export function create_fetch({ event, options, state,
|
|
17
|
-
|
|
18
|
-
const fetched = [];
|
|
19
|
-
|
|
20
|
-
const initial_cookies = cookie.parse(event.request.headers.get('cookie') || '');
|
|
21
|
-
|
|
22
|
-
/** @type {import('./types').Cookie[]} */
|
|
23
|
-
const set_cookies = [];
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @param {URL} url
|
|
27
|
-
* @param {string | null} header
|
|
28
|
-
*/
|
|
29
|
-
function get_cookie_header(url, header) {
|
|
30
|
-
/** @type {Record<string, string>} */
|
|
31
|
-
const new_cookies = {};
|
|
32
|
-
|
|
33
|
-
for (const cookie of set_cookies) {
|
|
34
|
-
if (!domain_matches(url.hostname, cookie.options.domain)) continue;
|
|
35
|
-
if (!path_matches(url.pathname, cookie.options.path)) continue;
|
|
36
|
-
|
|
37
|
-
new_cookies[cookie.name] = cookie.value;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// cookies from explicit `cookie` header take precedence over cookies previously set
|
|
41
|
-
// during this load with `set-cookie`, which take precedence over the cookies
|
|
42
|
-
// sent by the user agent
|
|
43
|
-
const combined_cookies = {
|
|
44
|
-
...initial_cookies,
|
|
45
|
-
...new_cookies,
|
|
46
|
-
...cookie.parse(header ?? '')
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
return Object.entries(combined_cookies)
|
|
50
|
-
.map(([name, value]) => `${name}=${value}`)
|
|
51
|
-
.join('; ');
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** @type {typeof fetch} */
|
|
55
|
-
const fetcher = async (info, init) => {
|
|
13
|
+
export function create_fetch({ event, options, state, get_cookie_header }) {
|
|
14
|
+
return async (info, init) => {
|
|
56
15
|
const request = normalize_fetch_input(info, init, event.url);
|
|
57
16
|
|
|
58
17
|
const request_body = init?.body;
|
|
@@ -60,7 +19,7 @@ export function create_fetch({ event, options, state, route, prerender_default,
|
|
|
60
19
|
/** @type {import('types').PrerenderDependency} */
|
|
61
20
|
let dependency;
|
|
62
21
|
|
|
63
|
-
|
|
22
|
+
return await options.hooks.handleFetch({
|
|
64
23
|
event,
|
|
65
24
|
request,
|
|
66
25
|
fetch: async (info, init) => {
|
|
@@ -174,11 +133,7 @@ export function create_fetch({ event, options, state, route, prerender_default,
|
|
|
174
133
|
throw new Error('Request body must be a string or TypedArray');
|
|
175
134
|
}
|
|
176
135
|
|
|
177
|
-
response = await respond(request, options,
|
|
178
|
-
prerender_default,
|
|
179
|
-
...state,
|
|
180
|
-
initiator: route
|
|
181
|
-
});
|
|
136
|
+
response = await respond(request, options, state);
|
|
182
137
|
|
|
183
138
|
if (state.prerendering) {
|
|
184
139
|
dependency = { response, body: null };
|
|
@@ -187,104 +142,22 @@ export function create_fetch({ event, options, state, route, prerender_default,
|
|
|
187
142
|
|
|
188
143
|
const set_cookie = response.headers.get('set-cookie');
|
|
189
144
|
if (set_cookie) {
|
|
190
|
-
|
|
191
|
-
...set_cookie_parser.
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
return response;
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
const proxy = new Proxy(response, {
|
|
204
|
-
get(response, key, _receiver) {
|
|
205
|
-
async function text() {
|
|
206
|
-
const body = await response.text();
|
|
207
|
-
|
|
208
|
-
if (!body || typeof body === 'string') {
|
|
209
|
-
const status_number = Number(response.status);
|
|
210
|
-
if (isNaN(status_number)) {
|
|
211
|
-
throw new Error(
|
|
212
|
-
`response.status is not a number. value: "${
|
|
213
|
-
response.status
|
|
214
|
-
}" type: ${typeof response.status}`
|
|
215
|
-
);
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
fetched.push({
|
|
219
|
-
url: request.url.startsWith(event.url.origin)
|
|
220
|
-
? request.url.slice(event.url.origin.length)
|
|
221
|
-
: request.url,
|
|
222
|
-
method: request.method,
|
|
223
|
-
request_body: /** @type {string | ArrayBufferView | undefined} */ (request_body),
|
|
224
|
-
response_body: body,
|
|
225
|
-
response: response
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
// ensure that excluded headers can't be read
|
|
229
|
-
const get = response.headers.get;
|
|
230
|
-
response.headers.get = (key) => {
|
|
231
|
-
const lower = key.toLowerCase();
|
|
232
|
-
const value = get.call(response.headers, lower);
|
|
233
|
-
if (value && !lower.startsWith('x-sveltekit-')) {
|
|
234
|
-
const included = resolve_opts.filterSerializedResponseHeaders(lower, value);
|
|
235
|
-
if (!included) {
|
|
236
|
-
throw new Error(
|
|
237
|
-
`Failed to get response header "${lower}" — it must be included by the \`filterSerializedResponseHeaders\` option: https://kit.svelte.dev/docs/hooks#handle`
|
|
238
|
-
);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
return value;
|
|
243
|
-
};
|
|
145
|
+
for (const str of set_cookie_parser.splitCookiesString(set_cookie)) {
|
|
146
|
+
const { name, value, ...options } = set_cookie_parser.parseString(str);
|
|
147
|
+
|
|
148
|
+
// options.sameSite is string, something more specific is required - type cast is safe
|
|
149
|
+
event.cookies.set(
|
|
150
|
+
name,
|
|
151
|
+
value,
|
|
152
|
+
/** @type {import('cookie').CookieSerializeOptions} */ (options)
|
|
153
|
+
);
|
|
244
154
|
}
|
|
245
|
-
|
|
246
|
-
if (dependency) {
|
|
247
|
-
dependency.body = body;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
return body;
|
|
251
155
|
}
|
|
252
156
|
|
|
253
|
-
|
|
254
|
-
return async () => {
|
|
255
|
-
const buffer = await response.arrayBuffer();
|
|
256
|
-
|
|
257
|
-
if (dependency) {
|
|
258
|
-
dependency.body = new Uint8Array(buffer);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// TODO should buffer be inlined into the page (albeit base64'd)?
|
|
262
|
-
// any conditions in which it shouldn't be?
|
|
263
|
-
|
|
264
|
-
return buffer;
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
if (key === 'text') {
|
|
269
|
-
return text;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
if (key === 'json') {
|
|
273
|
-
return async () => {
|
|
274
|
-
return JSON.parse(await text());
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
// TODO arrayBuffer?
|
|
279
|
-
|
|
280
|
-
return Reflect.get(response, key, response);
|
|
157
|
+
return response;
|
|
281
158
|
}
|
|
282
159
|
});
|
|
283
|
-
|
|
284
|
-
return proxy;
|
|
285
160
|
};
|
|
286
|
-
|
|
287
|
-
return { fetcher, fetched, cookies: set_cookies };
|
|
288
161
|
}
|
|
289
162
|
|
|
290
163
|
/**
|
|
@@ -10,6 +10,7 @@ import { render_data } from './data/index.js';
|
|
|
10
10
|
import { DATA_SUFFIX } from '../../constants.js';
|
|
11
11
|
import { add_cookies_to_headers, get_cookies } from './cookie.js';
|
|
12
12
|
import { HttpError } from '../control.js';
|
|
13
|
+
import { create_fetch } from './fetch.js';
|
|
13
14
|
|
|
14
15
|
/* global __SVELTEKIT_ADAPTER_NAME__ */
|
|
15
16
|
|
|
@@ -96,13 +97,15 @@ export async function respond(request, options, state) {
|
|
|
96
97
|
/** @type {Record<string, string>} */
|
|
97
98
|
const headers = {};
|
|
98
99
|
|
|
99
|
-
const { cookies, new_cookies } = get_cookies(request, url);
|
|
100
|
+
const { cookies, new_cookies, get_cookie_header } = get_cookies(request, url);
|
|
100
101
|
|
|
101
102
|
if (state.prerendering) disable_search(url);
|
|
102
103
|
|
|
103
104
|
/** @type {import('types').RequestEvent} */
|
|
104
105
|
const event = {
|
|
105
106
|
cookies,
|
|
107
|
+
// @ts-expect-error this is added in the next step, because `create_fetch` needs a reference to `event`
|
|
108
|
+
fetch: null,
|
|
106
109
|
getClientAddress:
|
|
107
110
|
state.getClientAddress ||
|
|
108
111
|
(() => {
|
|
@@ -138,6 +141,8 @@ export async function respond(request, options, state) {
|
|
|
138
141
|
url
|
|
139
142
|
};
|
|
140
143
|
|
|
144
|
+
event.fetch = create_fetch({ event, options, state, get_cookie_header });
|
|
145
|
+
|
|
141
146
|
// TODO remove this for 1.0
|
|
142
147
|
/**
|
|
143
148
|
* @param {string} property
|
|
@@ -215,7 +220,6 @@ export async function respond(request, options, state) {
|
|
|
215
220
|
error: null,
|
|
216
221
|
branch: [],
|
|
217
222
|
fetched: [],
|
|
218
|
-
cookies: [],
|
|
219
223
|
resolve_opts
|
|
220
224
|
});
|
|
221
225
|
}
|
|
@@ -295,7 +299,7 @@ export async function respond(request, options, state) {
|
|
|
295
299
|
response.headers.set(key, /** @type {string} */ (value));
|
|
296
300
|
}
|
|
297
301
|
}
|
|
298
|
-
add_cookies_to_headers(response.headers,
|
|
302
|
+
add_cookies_to_headers(response.headers, Object.values(new_cookies));
|
|
299
303
|
|
|
300
304
|
if (state.prerendering && event.routeId !== null) {
|
|
301
305
|
response.headers.set('x-sveltekit-routeid', encodeURI(event.routeId));
|
|
@@ -15,7 +15,6 @@ import {
|
|
|
15
15
|
is_action_json_request,
|
|
16
16
|
is_action_request
|
|
17
17
|
} from './actions.js';
|
|
18
|
-
import { create_fetch } from './fetch.js';
|
|
19
18
|
import { load_data, load_server_data } from './load_data.js';
|
|
20
19
|
import { render_response } from './render.js';
|
|
21
20
|
import { respond_with_error } from './respond_with_error.js';
|
|
@@ -37,6 +36,8 @@ export async function render_page(event, route, page, options, state, resolve_op
|
|
|
37
36
|
});
|
|
38
37
|
}
|
|
39
38
|
|
|
39
|
+
state.initiator = route;
|
|
40
|
+
|
|
40
41
|
if (is_action_json_request(event)) {
|
|
41
42
|
const node = await options.manifest._.nodes[page.leaf]();
|
|
42
43
|
if (node.server) {
|
|
@@ -93,20 +94,17 @@ export async function render_page(event, route, page, options, state, resolve_op
|
|
|
93
94
|
});
|
|
94
95
|
}
|
|
95
96
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
resolve_opts
|
|
103
|
-
});
|
|
97
|
+
// if we fetch any endpoints while loading data for this page, they should
|
|
98
|
+
// inherit the prerender option of the page
|
|
99
|
+
state.prerender_default = should_prerender;
|
|
100
|
+
|
|
101
|
+
/** @type {import('./types').Fetched[]} */
|
|
102
|
+
const fetched = [];
|
|
104
103
|
|
|
105
104
|
if (get_option(nodes, 'ssr') === false) {
|
|
106
105
|
return await render_response({
|
|
107
106
|
branch: [],
|
|
108
107
|
fetched,
|
|
109
|
-
cookies,
|
|
110
108
|
page_config: {
|
|
111
109
|
ssr: false,
|
|
112
110
|
csr: get_option(nodes, 'csr') ?? true
|
|
@@ -169,7 +167,7 @@ export async function render_page(event, route, page, options, state, resolve_op
|
|
|
169
167
|
try {
|
|
170
168
|
return await load_data({
|
|
171
169
|
event,
|
|
172
|
-
|
|
170
|
+
fetched,
|
|
173
171
|
node,
|
|
174
172
|
parent: async () => {
|
|
175
173
|
const data = {};
|
|
@@ -178,6 +176,7 @@ export async function render_page(event, route, page, options, state, resolve_op
|
|
|
178
176
|
}
|
|
179
177
|
return data;
|
|
180
178
|
},
|
|
179
|
+
resolve_opts,
|
|
181
180
|
server_data_promise: server_promises[i],
|
|
182
181
|
state
|
|
183
182
|
});
|
|
@@ -217,7 +216,7 @@ export async function render_page(event, route, page, options, state, resolve_op
|
|
|
217
216
|
});
|
|
218
217
|
}
|
|
219
218
|
|
|
220
|
-
return redirect_response(err.status, err.location
|
|
219
|
+
return redirect_response(err.status, err.location);
|
|
221
220
|
}
|
|
222
221
|
|
|
223
222
|
const status = err instanceof HttpError ? err.status : 500;
|
|
@@ -244,8 +243,7 @@ export async function render_page(event, route, page, options, state, resolve_op
|
|
|
244
243
|
data: null,
|
|
245
244
|
server_data: null
|
|
246
245
|
}),
|
|
247
|
-
fetched
|
|
248
|
-
cookies
|
|
246
|
+
fetched
|
|
249
247
|
});
|
|
250
248
|
}
|
|
251
249
|
}
|
|
@@ -286,8 +284,7 @@ export async function render_page(event, route, page, options, state, resolve_op
|
|
|
286
284
|
error: null,
|
|
287
285
|
branch: compact(branch),
|
|
288
286
|
action_result,
|
|
289
|
-
fetched
|
|
290
|
-
cookies
|
|
287
|
+
fetched
|
|
291
288
|
});
|
|
292
289
|
} catch (error) {
|
|
293
290
|
// if we end up here, it means the data loaded successfull
|
|
@@ -68,27 +68,126 @@ export async function load_server_data({ event, state, node, parent }) {
|
|
|
68
68
|
* Calls the user's `load` function.
|
|
69
69
|
* @param {{
|
|
70
70
|
* event: import('types').RequestEvent;
|
|
71
|
-
*
|
|
71
|
+
* fetched: import('./types').Fetched[];
|
|
72
72
|
* node: import('types').SSRNode | undefined;
|
|
73
73
|
* parent: () => Promise<Record<string, any>>;
|
|
74
|
+
* resolve_opts: import('types').RequiredResolveOptions;
|
|
74
75
|
* server_data_promise: Promise<import('types').ServerDataNode | null>;
|
|
75
76
|
* state: import('types').SSRState;
|
|
76
77
|
* }} opts
|
|
77
78
|
* @returns {Promise<Record<string, any> | null>}
|
|
78
79
|
*/
|
|
79
|
-
export async function load_data({
|
|
80
|
+
export async function load_data({
|
|
81
|
+
event,
|
|
82
|
+
fetched,
|
|
83
|
+
node,
|
|
84
|
+
parent,
|
|
85
|
+
server_data_promise,
|
|
86
|
+
state,
|
|
87
|
+
resolve_opts
|
|
88
|
+
}) {
|
|
80
89
|
const server_data_node = await server_data_promise;
|
|
81
90
|
|
|
82
91
|
if (!node?.shared?.load) {
|
|
83
92
|
return server_data_node?.data ?? null;
|
|
84
93
|
}
|
|
85
94
|
|
|
95
|
+
/** @type {import('types').LoadEvent} */
|
|
86
96
|
const load_event = {
|
|
87
97
|
url: event.url,
|
|
88
98
|
params: event.params,
|
|
89
99
|
data: server_data_node?.data ?? null,
|
|
90
100
|
routeId: event.routeId,
|
|
91
|
-
fetch:
|
|
101
|
+
fetch: async (input, init) => {
|
|
102
|
+
const response = await event.fetch(input, init);
|
|
103
|
+
|
|
104
|
+
const url = new URL(input instanceof Request ? input.url : input, event.url);
|
|
105
|
+
const same_origin = url.origin === event.url.origin;
|
|
106
|
+
|
|
107
|
+
const request_body = init?.body;
|
|
108
|
+
const dependency = same_origin && state.prerendering?.dependencies.get(url.pathname);
|
|
109
|
+
|
|
110
|
+
const proxy = new Proxy(response, {
|
|
111
|
+
get(response, key, _receiver) {
|
|
112
|
+
async function text() {
|
|
113
|
+
const body = await response.text();
|
|
114
|
+
|
|
115
|
+
if (!body || typeof body === 'string') {
|
|
116
|
+
const status_number = Number(response.status);
|
|
117
|
+
if (isNaN(status_number)) {
|
|
118
|
+
throw new Error(
|
|
119
|
+
`response.status is not a number. value: "${
|
|
120
|
+
response.status
|
|
121
|
+
}" type: ${typeof response.status}`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
fetched.push({
|
|
126
|
+
url: same_origin ? url.href.slice(event.url.origin.length) : url.href,
|
|
127
|
+
method: event.request.method,
|
|
128
|
+
request_body: /** @type {string | ArrayBufferView | undefined} */ (request_body),
|
|
129
|
+
response_body: body,
|
|
130
|
+
response: response
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// ensure that excluded headers can't be read
|
|
134
|
+
const get = response.headers.get;
|
|
135
|
+
response.headers.get = (key) => {
|
|
136
|
+
const lower = key.toLowerCase();
|
|
137
|
+
const value = get.call(response.headers, lower);
|
|
138
|
+
if (value && !lower.startsWith('x-sveltekit-')) {
|
|
139
|
+
const included = resolve_opts.filterSerializedResponseHeaders(lower, value);
|
|
140
|
+
if (!included) {
|
|
141
|
+
throw new Error(
|
|
142
|
+
`Failed to get response header "${lower}" — it must be included by the \`filterSerializedResponseHeaders\` option: https://kit.svelte.dev/docs/hooks#handle`
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return value;
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (dependency) {
|
|
152
|
+
dependency.body = body;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return body;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (key === 'arrayBuffer') {
|
|
159
|
+
return async () => {
|
|
160
|
+
const buffer = await response.arrayBuffer();
|
|
161
|
+
|
|
162
|
+
if (dependency) {
|
|
163
|
+
dependency.body = new Uint8Array(buffer);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// TODO should buffer be inlined into the page (albeit base64'd)?
|
|
167
|
+
// any conditions in which it shouldn't be?
|
|
168
|
+
|
|
169
|
+
return buffer;
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (key === 'text') {
|
|
174
|
+
return text;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (key === 'json') {
|
|
178
|
+
return async () => {
|
|
179
|
+
return JSON.parse(await text());
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// TODO arrayBuffer?
|
|
184
|
+
|
|
185
|
+
return Reflect.get(response, key, response);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
return proxy;
|
|
190
|
+
},
|
|
92
191
|
setHeaders: event.setHeaders,
|
|
93
192
|
depends: () => {},
|
|
94
193
|
parent
|
|
@@ -4,7 +4,6 @@ import { hash } from '../../hash.js';
|
|
|
4
4
|
import { serialize_data } from './serialize_data.js';
|
|
5
5
|
import { s } from '../../../utils/misc.js';
|
|
6
6
|
import { Csp } from './csp.js';
|
|
7
|
-
import { add_cookies_to_headers } from '../cookie.js';
|
|
8
7
|
|
|
9
8
|
// TODO rename this function/module
|
|
10
9
|
|
|
@@ -18,7 +17,6 @@ const updated = {
|
|
|
18
17
|
* @param {{
|
|
19
18
|
* branch: Array<import('./types').Loaded>;
|
|
20
19
|
* fetched: Array<import('./types').Fetched>;
|
|
21
|
-
* cookies: import('./types').Cookie[];
|
|
22
20
|
* options: import('types').SSROptions;
|
|
23
21
|
* state: import('types').SSRState;
|
|
24
22
|
* page_config: { ssr: boolean; csr: boolean };
|
|
@@ -32,7 +30,6 @@ const updated = {
|
|
|
32
30
|
export async function render_response({
|
|
33
31
|
branch,
|
|
34
32
|
fetched,
|
|
35
|
-
cookies,
|
|
36
33
|
options,
|
|
37
34
|
state,
|
|
38
35
|
page_config,
|
|
@@ -329,8 +326,6 @@ export async function render_response({
|
|
|
329
326
|
headers.set('content-security-policy-report-only', report_only_header);
|
|
330
327
|
}
|
|
331
328
|
|
|
332
|
-
add_cookies_to_headers(headers, cookies);
|
|
333
|
-
|
|
334
329
|
if (link_header_preloads.size) {
|
|
335
330
|
headers.set('link', Array.from(link_header_preloads).join(', '));
|
|
336
331
|
}
|
|
@@ -2,12 +2,11 @@ import { render_response } from './render.js';
|
|
|
2
2
|
import { load_data, load_server_data } from './load_data.js';
|
|
3
3
|
import {
|
|
4
4
|
handle_error_and_jsonify,
|
|
5
|
-
GENERIC_ERROR,
|
|
6
5
|
get_option,
|
|
7
6
|
static_error_page,
|
|
8
|
-
redirect_response
|
|
7
|
+
redirect_response,
|
|
8
|
+
GENERIC_ERROR
|
|
9
9
|
} from '../utils.js';
|
|
10
|
-
import { create_fetch } from './fetch.js';
|
|
11
10
|
import { HttpError, Redirect } from '../../control.js';
|
|
12
11
|
|
|
13
12
|
/**
|
|
@@ -27,13 +26,8 @@ import { HttpError, Redirect } from '../../control.js';
|
|
|
27
26
|
* }} opts
|
|
28
27
|
*/
|
|
29
28
|
export async function respond_with_error({ event, options, state, status, error, resolve_opts }) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
options,
|
|
33
|
-
state,
|
|
34
|
-
route: GENERIC_ERROR,
|
|
35
|
-
resolve_opts
|
|
36
|
-
});
|
|
29
|
+
/** @type {import('./types').Fetched[]} */
|
|
30
|
+
const fetched = [];
|
|
37
31
|
|
|
38
32
|
try {
|
|
39
33
|
const branch = [];
|
|
@@ -41,6 +35,8 @@ export async function respond_with_error({ event, options, state, status, error,
|
|
|
41
35
|
const ssr = get_option([default_layout], 'ssr') ?? true;
|
|
42
36
|
|
|
43
37
|
if (ssr) {
|
|
38
|
+
state.initiator = GENERIC_ERROR;
|
|
39
|
+
|
|
44
40
|
const server_data_promise = load_server_data({
|
|
45
41
|
event,
|
|
46
42
|
state,
|
|
@@ -52,9 +48,10 @@ export async function respond_with_error({ event, options, state, status, error,
|
|
|
52
48
|
|
|
53
49
|
const data = await load_data({
|
|
54
50
|
event,
|
|
55
|
-
|
|
51
|
+
fetched,
|
|
56
52
|
node: default_layout,
|
|
57
53
|
parent: async () => ({}),
|
|
54
|
+
resolve_opts,
|
|
58
55
|
server_data_promise,
|
|
59
56
|
state
|
|
60
57
|
});
|
|
@@ -84,7 +81,6 @@ export async function respond_with_error({ event, options, state, status, error,
|
|
|
84
81
|
error: handle_error_and_jsonify(event, options, error),
|
|
85
82
|
branch,
|
|
86
83
|
fetched,
|
|
87
|
-
cookies,
|
|
88
84
|
event,
|
|
89
85
|
resolve_opts
|
|
90
86
|
});
|
|
@@ -92,7 +88,7 @@ export async function respond_with_error({ event, options, state, status, error,
|
|
|
92
88
|
// Edge case: If route is a 404 and the user redirects to somewhere from the root layout,
|
|
93
89
|
// we end up here.
|
|
94
90
|
if (error instanceof Redirect) {
|
|
95
|
-
return redirect_response(error.status, error.location
|
|
91
|
+
return redirect_response(error.status, error.location);
|
|
96
92
|
}
|
|
97
93
|
|
|
98
94
|
return static_error_page(
|
|
@@ -2,7 +2,6 @@ import * as devalue from 'devalue';
|
|
|
2
2
|
import { DATA_SUFFIX } from '../../constants.js';
|
|
3
3
|
import { negotiate } from '../../utils/http.js';
|
|
4
4
|
import { HttpError } from '../control.js';
|
|
5
|
-
import { add_cookies_to_headers } from './cookie.js';
|
|
6
5
|
|
|
7
6
|
/** @param {any} body */
|
|
8
7
|
export function is_pojo(body) {
|
|
@@ -167,13 +166,11 @@ export function handle_error_and_jsonify(event, options, error) {
|
|
|
167
166
|
/**
|
|
168
167
|
* @param {number} status
|
|
169
168
|
* @param {string} location
|
|
170
|
-
* @param {import('./page/types.js').Cookie[]} [cookies]
|
|
171
169
|
*/
|
|
172
|
-
export function redirect_response(status, location
|
|
170
|
+
export function redirect_response(status, location) {
|
|
173
171
|
const response = new Response(undefined, {
|
|
174
172
|
status,
|
|
175
173
|
headers: { location }
|
|
176
174
|
});
|
|
177
|
-
add_cookies_to_headers(response.headers, cookies);
|
|
178
175
|
return response;
|
|
179
176
|
}
|
package/types/index.d.ts
CHANGED