@sveltejs/kit 1.0.0-next.5 → 1.0.0-next.500
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/README.md +12 -9
- package/package.json +94 -52
- package/postinstall.js +38 -0
- package/scripts/special-types/$env+dynamic+private.md +10 -0
- package/scripts/special-types/$env+dynamic+public.md +8 -0
- package/scripts/special-types/$env+static+private.md +19 -0
- package/scripts/special-types/$env+static+public.md +7 -0
- package/scripts/special-types/$lib.md +5 -0
- package/src/cli.js +108 -0
- package/src/constants.js +7 -0
- package/src/core/adapt/builder.js +206 -0
- package/src/core/adapt/index.js +31 -0
- package/src/core/config/default-error.html +56 -0
- package/src/core/config/index.js +110 -0
- package/src/core/config/options.js +504 -0
- package/src/core/config/types.d.ts +1 -0
- package/src/core/env.js +121 -0
- package/src/core/generate_manifest/index.js +93 -0
- package/src/core/prerender/crawl.js +198 -0
- package/src/core/prerender/entities.js +2252 -0
- package/src/core/prerender/prerender.js +431 -0
- package/src/core/prerender/queue.js +80 -0
- package/src/core/sync/create_manifest_data/index.js +488 -0
- package/src/core/sync/create_manifest_data/types.d.ts +37 -0
- package/src/core/sync/sync.js +70 -0
- package/src/core/sync/utils.js +33 -0
- package/src/core/sync/write_ambient.js +53 -0
- package/src/core/sync/write_client_manifest.js +106 -0
- package/src/core/sync/write_matchers.js +25 -0
- package/src/core/sync/write_root.js +91 -0
- package/src/core/sync/write_tsconfig.js +195 -0
- package/src/core/sync/write_types/index.js +678 -0
- package/src/core/utils.js +70 -0
- package/src/exports/hooks/index.js +1 -0
- package/src/exports/hooks/sequence.js +44 -0
- package/src/exports/index.js +45 -0
- package/src/exports/node/index.js +173 -0
- package/src/exports/node/polyfills.js +41 -0
- package/src/exports/vite/build/build_server.js +378 -0
- package/src/exports/vite/build/build_service_worker.js +90 -0
- package/src/exports/vite/build/utils.js +180 -0
- package/src/exports/vite/dev/index.js +577 -0
- package/src/exports/vite/graph_analysis/index.js +277 -0
- package/src/exports/vite/graph_analysis/types.d.ts +5 -0
- package/src/exports/vite/graph_analysis/utils.js +30 -0
- package/src/exports/vite/index.js +598 -0
- package/src/exports/vite/preview/index.js +189 -0
- package/src/exports/vite/types.d.ts +3 -0
- package/src/exports/vite/utils.js +157 -0
- package/src/runtime/app/env.js +1 -0
- package/src/runtime/app/environment.js +11 -0
- package/src/runtime/app/forms.js +114 -0
- package/src/runtime/app/navigation.js +23 -0
- package/src/runtime/app/paths.js +1 -0
- package/src/runtime/app/stores.js +102 -0
- package/src/runtime/client/ambient.d.ts +26 -0
- package/src/runtime/client/client.js +1583 -0
- package/src/runtime/client/fetcher.js +107 -0
- package/src/runtime/client/parse.js +60 -0
- package/src/runtime/client/singletons.js +21 -0
- package/src/runtime/client/start.js +37 -0
- package/src/runtime/client/types.d.ts +84 -0
- package/src/runtime/client/utils.js +159 -0
- package/src/runtime/components/error.svelte +16 -0
- package/{assets → src/runtime}/components/layout.svelte +0 -0
- package/src/runtime/control.js +98 -0
- package/src/runtime/env/dynamic/private.js +1 -0
- package/src/runtime/env/dynamic/public.js +1 -0
- package/src/runtime/env-private.js +6 -0
- package/src/runtime/env-public.js +6 -0
- package/src/runtime/env.js +6 -0
- package/src/runtime/hash.js +16 -0
- package/src/runtime/paths.js +11 -0
- package/src/runtime/server/cookie.js +127 -0
- package/src/runtime/server/data/index.js +136 -0
- package/src/runtime/server/endpoint.js +90 -0
- package/src/runtime/server/index.js +340 -0
- package/src/runtime/server/page/actions.js +243 -0
- package/src/runtime/server/page/crypto.js +239 -0
- package/src/runtime/server/page/csp.js +250 -0
- package/src/runtime/server/page/fetch.js +301 -0
- package/src/runtime/server/page/index.js +304 -0
- package/src/runtime/server/page/load_data.js +124 -0
- package/src/runtime/server/page/render.js +342 -0
- package/src/runtime/server/page/respond_with_error.js +104 -0
- package/src/runtime/server/page/serialize_data.js +87 -0
- package/src/runtime/server/page/types.d.ts +41 -0
- package/src/runtime/server/utils.js +179 -0
- package/src/utils/array.js +9 -0
- package/src/utils/error.js +22 -0
- package/src/utils/escape.js +46 -0
- package/src/utils/filesystem.js +137 -0
- package/src/utils/functions.js +16 -0
- package/src/utils/http.js +55 -0
- package/src/utils/misc.js +1 -0
- package/src/utils/routing.js +117 -0
- package/src/utils/unit_test.js +11 -0
- package/src/utils/url.js +142 -0
- package/svelte-kit.js +2 -0
- package/types/ambient.d.ts +426 -0
- package/types/index.d.ts +444 -0
- package/types/internal.d.ts +378 -0
- package/types/private.d.ts +224 -0
- package/CHANGELOG.md +0 -177
- package/assets/components/error.svelte +0 -13
- package/assets/runtime/app/navigation.js +0 -47
- package/assets/runtime/app/navigation.js.map +0 -1
- package/assets/runtime/app/stores.js +0 -78
- package/assets/runtime/app/stores.js.map +0 -1
- package/assets/runtime/internal/singletons.js +0 -10
- package/assets/runtime/internal/singletons.js.map +0 -1
- package/assets/runtime/internal/start.js +0 -517
- package/assets/runtime/internal/start.js.map +0 -1
- package/dist/api.js +0 -40
- package/dist/api.js.map +0 -1
- package/dist/cli.js +0 -128
- package/dist/cli.js.map +0 -1
- package/dist/create_app.js +0 -550
- package/dist/create_app.js.map +0 -1
- package/dist/index.js +0 -8331
- package/dist/index.js.map +0 -1
- package/dist/index2.js +0 -509
- package/dist/index2.js.map +0 -1
- package/dist/index3.js +0 -63
- package/dist/index3.js.map +0 -1
- package/dist/index4.js +0 -466
- package/dist/index4.js.map +0 -1
- package/dist/index5.js +0 -276
- package/dist/index5.js.map +0 -1
- package/dist/package.js +0 -235
- package/dist/package.js.map +0 -1
- package/dist/renderer.js +0 -2398
- package/dist/renderer.js.map +0 -1
- package/dist/standard.js +0 -101
- package/dist/standard.js.map +0 -1
- package/dist/utils.js +0 -58
- package/dist/utils.js.map +0 -1
- package/svelte-kit +0 -3
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { escape_html_attr } from '../../../utils/escape.js';
|
|
2
|
+
import { base64, sha256 } from './crypto.js';
|
|
3
|
+
|
|
4
|
+
const array = new Uint8Array(16);
|
|
5
|
+
|
|
6
|
+
function generate_nonce() {
|
|
7
|
+
crypto.getRandomValues(array);
|
|
8
|
+
return base64(array);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const quoted = new Set([
|
|
12
|
+
'self',
|
|
13
|
+
'unsafe-eval',
|
|
14
|
+
'unsafe-hashes',
|
|
15
|
+
'unsafe-inline',
|
|
16
|
+
'none',
|
|
17
|
+
'strict-dynamic',
|
|
18
|
+
'report-sample',
|
|
19
|
+
'wasm-unsafe-eval'
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
const crypto_pattern = /^(nonce|sha\d\d\d)-/;
|
|
23
|
+
|
|
24
|
+
// CSP and CSP Report Only are extremely similar with a few caveats
|
|
25
|
+
// the easiest/DRYest way to express this is with some private encapsulation
|
|
26
|
+
class BaseProvider {
|
|
27
|
+
/** @type {boolean} */
|
|
28
|
+
#use_hashes;
|
|
29
|
+
|
|
30
|
+
/** @type {boolean} */
|
|
31
|
+
#script_needs_csp;
|
|
32
|
+
|
|
33
|
+
/** @type {boolean} */
|
|
34
|
+
#style_needs_csp;
|
|
35
|
+
|
|
36
|
+
/** @type {import('types').CspDirectives} */
|
|
37
|
+
#directives;
|
|
38
|
+
|
|
39
|
+
/** @type {import('types').Csp.Source[]} */
|
|
40
|
+
#script_src;
|
|
41
|
+
|
|
42
|
+
/** @type {import('types').Csp.Source[]} */
|
|
43
|
+
#style_src;
|
|
44
|
+
|
|
45
|
+
/** @type {string} */
|
|
46
|
+
#nonce;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @param {boolean} use_hashes
|
|
50
|
+
* @param {import('types').CspDirectives} directives
|
|
51
|
+
* @param {string} nonce
|
|
52
|
+
* @param {boolean} dev
|
|
53
|
+
*/
|
|
54
|
+
constructor(use_hashes, directives, nonce, dev) {
|
|
55
|
+
this.#use_hashes = use_hashes;
|
|
56
|
+
this.#directives = dev ? { ...directives } : directives; // clone in dev so we can safely mutate
|
|
57
|
+
|
|
58
|
+
const d = this.#directives;
|
|
59
|
+
|
|
60
|
+
if (dev) {
|
|
61
|
+
// remove strict-dynamic in dev...
|
|
62
|
+
// TODO reinstate this if we can figure out how to make strict-dynamic work
|
|
63
|
+
// if (d['default-src']) {
|
|
64
|
+
// d['default-src'] = d['default-src'].filter((name) => name !== 'strict-dynamic');
|
|
65
|
+
// if (d['default-src'].length === 0) delete d['default-src'];
|
|
66
|
+
// }
|
|
67
|
+
|
|
68
|
+
// if (d['script-src']) {
|
|
69
|
+
// d['script-src'] = d['script-src'].filter((name) => name !== 'strict-dynamic');
|
|
70
|
+
// if (d['script-src'].length === 0) delete d['script-src'];
|
|
71
|
+
// }
|
|
72
|
+
|
|
73
|
+
const effective_style_src = d['style-src'] || d['default-src'];
|
|
74
|
+
|
|
75
|
+
// ...and add unsafe-inline so we can inject <style> elements
|
|
76
|
+
if (effective_style_src && !effective_style_src.includes('unsafe-inline')) {
|
|
77
|
+
d['style-src'] = [...effective_style_src, 'unsafe-inline'];
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
this.#script_src = [];
|
|
82
|
+
this.#style_src = [];
|
|
83
|
+
|
|
84
|
+
const effective_script_src = d['script-src'] || d['default-src'];
|
|
85
|
+
const effective_style_src = d['style-src'] || d['default-src'];
|
|
86
|
+
|
|
87
|
+
this.#script_needs_csp =
|
|
88
|
+
!!effective_script_src &&
|
|
89
|
+
effective_script_src.filter((value) => value !== 'unsafe-inline').length > 0;
|
|
90
|
+
|
|
91
|
+
this.#style_needs_csp =
|
|
92
|
+
!dev &&
|
|
93
|
+
!!effective_style_src &&
|
|
94
|
+
effective_style_src.filter((value) => value !== 'unsafe-inline').length > 0;
|
|
95
|
+
|
|
96
|
+
this.script_needs_nonce = this.#script_needs_csp && !this.#use_hashes;
|
|
97
|
+
this.style_needs_nonce = this.#style_needs_csp && !this.#use_hashes;
|
|
98
|
+
this.#nonce = nonce;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** @param {string} content */
|
|
102
|
+
add_script(content) {
|
|
103
|
+
if (this.#script_needs_csp) {
|
|
104
|
+
if (this.#use_hashes) {
|
|
105
|
+
this.#script_src.push(`sha256-${sha256(content)}`);
|
|
106
|
+
} else if (this.#script_src.length === 0) {
|
|
107
|
+
this.#script_src.push(`nonce-${this.#nonce}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** @param {string} content */
|
|
113
|
+
add_style(content) {
|
|
114
|
+
if (this.#style_needs_csp) {
|
|
115
|
+
if (this.#use_hashes) {
|
|
116
|
+
this.#style_src.push(`sha256-${sha256(content)}`);
|
|
117
|
+
} else if (this.#style_src.length === 0) {
|
|
118
|
+
this.#style_src.push(`nonce-${this.#nonce}`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @param {boolean} [is_meta]
|
|
125
|
+
*/
|
|
126
|
+
get_header(is_meta = false) {
|
|
127
|
+
const header = [];
|
|
128
|
+
|
|
129
|
+
// due to browser inconsistencies, we can't append sources to default-src
|
|
130
|
+
// (specifically, Firefox appears to not ignore nonce-{nonce} directives
|
|
131
|
+
// on default-src), so we ensure that script-src and style-src exist
|
|
132
|
+
|
|
133
|
+
const directives = { ...this.#directives };
|
|
134
|
+
|
|
135
|
+
if (this.#style_src.length > 0) {
|
|
136
|
+
directives['style-src'] = [
|
|
137
|
+
...(directives['style-src'] || directives['default-src'] || []),
|
|
138
|
+
...this.#style_src
|
|
139
|
+
];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (this.#script_src.length > 0) {
|
|
143
|
+
directives['script-src'] = [
|
|
144
|
+
...(directives['script-src'] || directives['default-src'] || []),
|
|
145
|
+
...this.#script_src
|
|
146
|
+
];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
for (const key in directives) {
|
|
150
|
+
if (is_meta && (key === 'frame-ancestors' || key === 'report-uri' || key === 'sandbox')) {
|
|
151
|
+
// these values cannot be used with a <meta> tag
|
|
152
|
+
// TODO warn?
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// @ts-expect-error gimme a break typescript, `key` is obviously a member of internal_directives
|
|
157
|
+
const value = /** @type {string[] | true} */ (directives[key]);
|
|
158
|
+
|
|
159
|
+
if (!value) continue;
|
|
160
|
+
|
|
161
|
+
const directive = [key];
|
|
162
|
+
if (Array.isArray(value)) {
|
|
163
|
+
value.forEach((value) => {
|
|
164
|
+
if (quoted.has(value) || crypto_pattern.test(value)) {
|
|
165
|
+
directive.push(`'${value}'`);
|
|
166
|
+
} else {
|
|
167
|
+
directive.push(value);
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
header.push(directive.join(' '));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return header.join('; ');
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
class CspProvider extends BaseProvider {
|
|
180
|
+
get_meta() {
|
|
181
|
+
const content = escape_html_attr(this.get_header(true));
|
|
182
|
+
return `<meta http-equiv="content-security-policy" content=${content}>`;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
class CspReportOnlyProvider extends BaseProvider {
|
|
187
|
+
/**
|
|
188
|
+
* @param {boolean} use_hashes
|
|
189
|
+
* @param {import('types').CspDirectives} directives
|
|
190
|
+
* @param {string} nonce
|
|
191
|
+
* @param {boolean} dev
|
|
192
|
+
*/
|
|
193
|
+
constructor(use_hashes, directives, nonce, dev) {
|
|
194
|
+
super(use_hashes, directives, nonce, dev);
|
|
195
|
+
|
|
196
|
+
if (Object.values(directives).filter((v) => !!v).length > 0) {
|
|
197
|
+
// If we're generating content-security-policy-report-only,
|
|
198
|
+
// if there are any directives, we need a report-uri or report-to (or both)
|
|
199
|
+
// else it's just an expensive noop.
|
|
200
|
+
const has_report_to = directives['report-to']?.length ?? 0 > 0;
|
|
201
|
+
const has_report_uri = directives['report-uri']?.length ?? 0 > 0;
|
|
202
|
+
if (!has_report_to && !has_report_uri) {
|
|
203
|
+
throw Error(
|
|
204
|
+
'`content-security-policy-report-only` must be specified with either the `report-to` or `report-uri` directives, or both'
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export class Csp {
|
|
212
|
+
/** @readonly */
|
|
213
|
+
nonce = generate_nonce();
|
|
214
|
+
|
|
215
|
+
/** @type {CspProvider} */
|
|
216
|
+
csp_provider;
|
|
217
|
+
|
|
218
|
+
/** @type {CspReportOnlyProvider} */
|
|
219
|
+
report_only_provider;
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* @param {import('./types').CspConfig} config
|
|
223
|
+
* @param {import('./types').CspOpts} opts
|
|
224
|
+
*/
|
|
225
|
+
constructor({ mode, directives, reportOnly }, { prerender, dev }) {
|
|
226
|
+
const use_hashes = mode === 'hash' || (mode === 'auto' && prerender);
|
|
227
|
+
this.csp_provider = new CspProvider(use_hashes, directives, this.nonce, dev);
|
|
228
|
+
this.report_only_provider = new CspReportOnlyProvider(use_hashes, reportOnly, this.nonce, dev);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
get script_needs_nonce() {
|
|
232
|
+
return this.csp_provider.script_needs_nonce || this.report_only_provider.script_needs_nonce;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
get style_needs_nonce() {
|
|
236
|
+
return this.csp_provider.style_needs_nonce || this.report_only_provider.style_needs_nonce;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/** @param {string} content */
|
|
240
|
+
add_script(content) {
|
|
241
|
+
this.csp_provider.add_script(content);
|
|
242
|
+
this.report_only_provider.add_script(content);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/** @param {string} content */
|
|
246
|
+
add_style(content) {
|
|
247
|
+
this.csp_provider.add_style(content);
|
|
248
|
+
this.report_only_provider.add_style(content);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import * as cookie from 'cookie';
|
|
2
|
+
import * as set_cookie_parser from 'set-cookie-parser';
|
|
3
|
+
import { respond } from '../index.js';
|
|
4
|
+
import { domain_matches, path_matches } from '../cookie.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @param {{
|
|
8
|
+
* event: import('types').RequestEvent;
|
|
9
|
+
* options: import('types').SSROptions;
|
|
10
|
+
* state: import('types').SSRState;
|
|
11
|
+
* route: import('types').SSRRoute | import('types').SSRErrorPage;
|
|
12
|
+
* prerender_default?: import('types').PrerenderOption;
|
|
13
|
+
* resolve_opts: import('types').RequiredResolveOptions;
|
|
14
|
+
* }} opts
|
|
15
|
+
*/
|
|
16
|
+
export function create_fetch({ event, options, state, route, prerender_default, resolve_opts }) {
|
|
17
|
+
/** @type {import('./types').Fetched[]} */
|
|
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) => {
|
|
56
|
+
const request = normalize_fetch_input(info, init, event.url);
|
|
57
|
+
|
|
58
|
+
const request_body = init?.body;
|
|
59
|
+
|
|
60
|
+
/** @type {import('types').PrerenderDependency} */
|
|
61
|
+
let dependency;
|
|
62
|
+
|
|
63
|
+
const response = await options.hooks.handleFetch({
|
|
64
|
+
event,
|
|
65
|
+
request,
|
|
66
|
+
fetch: async (info, init) => {
|
|
67
|
+
const request = normalize_fetch_input(info, init, event.url);
|
|
68
|
+
|
|
69
|
+
const url = new URL(request.url);
|
|
70
|
+
|
|
71
|
+
if (!request.headers.has('origin')) {
|
|
72
|
+
request.headers.set('origin', event.url.origin);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Remove Origin, according to https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin#description
|
|
76
|
+
if (
|
|
77
|
+
(request.method === 'GET' || request.method === 'HEAD') &&
|
|
78
|
+
((request.mode === 'no-cors' && url.origin !== event.url.origin) ||
|
|
79
|
+
url.origin === event.url.origin)
|
|
80
|
+
) {
|
|
81
|
+
request.headers.delete('origin');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (url.origin !== event.url.origin) {
|
|
85
|
+
// allow cookie passthrough for "same-origin"
|
|
86
|
+
// if SvelteKit is serving my.domain.com:
|
|
87
|
+
// - domain.com WILL NOT receive cookies
|
|
88
|
+
// - my.domain.com WILL receive cookies
|
|
89
|
+
// - api.domain.dom WILL NOT receive cookies
|
|
90
|
+
// - sub.my.domain.com WILL receive cookies
|
|
91
|
+
// ports do not affect the resolution
|
|
92
|
+
// leading dot prevents mydomain.com matching domain.com
|
|
93
|
+
if (
|
|
94
|
+
`.${url.hostname}`.endsWith(`.${event.url.hostname}`) &&
|
|
95
|
+
request.credentials !== 'omit'
|
|
96
|
+
) {
|
|
97
|
+
const cookie = get_cookie_header(url, request.headers.get('cookie'));
|
|
98
|
+
if (cookie) request.headers.set('cookie', cookie);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
let response = await fetch(request);
|
|
102
|
+
|
|
103
|
+
if (request.mode === 'no-cors') {
|
|
104
|
+
response = new Response('', {
|
|
105
|
+
status: response.status,
|
|
106
|
+
statusText: response.statusText,
|
|
107
|
+
headers: response.headers
|
|
108
|
+
});
|
|
109
|
+
} else {
|
|
110
|
+
if (url.origin !== event.url.origin) {
|
|
111
|
+
const acao = response.headers.get('access-control-allow-origin');
|
|
112
|
+
if (!acao || (acao !== event.url.origin && acao !== '*')) {
|
|
113
|
+
throw new Error(
|
|
114
|
+
`CORS error: ${
|
|
115
|
+
acao ? 'Incorrect' : 'No'
|
|
116
|
+
} 'Access-Control-Allow-Origin' header is present on the requested resource`
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return response;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** @type {Response} */
|
|
126
|
+
let response;
|
|
127
|
+
|
|
128
|
+
// handle fetch requests for static assets. e.g. prebaked data, etc.
|
|
129
|
+
// we need to support everything the browser's fetch supports
|
|
130
|
+
const prefix = options.paths.assets || options.paths.base;
|
|
131
|
+
const decoded = decodeURIComponent(url.pathname);
|
|
132
|
+
const filename = (
|
|
133
|
+
decoded.startsWith(prefix) ? decoded.slice(prefix.length) : decoded
|
|
134
|
+
).slice(1);
|
|
135
|
+
const filename_html = `${filename}/index.html`; // path may also match path/index.html
|
|
136
|
+
|
|
137
|
+
const is_asset = options.manifest.assets.has(filename);
|
|
138
|
+
const is_asset_html = options.manifest.assets.has(filename_html);
|
|
139
|
+
|
|
140
|
+
if (is_asset || is_asset_html) {
|
|
141
|
+
const file = is_asset ? filename : filename_html;
|
|
142
|
+
|
|
143
|
+
if (options.read) {
|
|
144
|
+
const type = is_asset
|
|
145
|
+
? options.manifest.mimeTypes[filename.slice(filename.lastIndexOf('.'))]
|
|
146
|
+
: 'text/html';
|
|
147
|
+
|
|
148
|
+
return new Response(options.read(file), {
|
|
149
|
+
headers: type ? { 'content-type': type } : {}
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return await fetch(request);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (request.credentials !== 'omit') {
|
|
157
|
+
const cookie = get_cookie_header(url, request.headers.get('cookie'));
|
|
158
|
+
if (cookie) {
|
|
159
|
+
request.headers.set('cookie', cookie);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const authorization = event.request.headers.get('authorization');
|
|
163
|
+
if (authorization && !request.headers.has('authorization')) {
|
|
164
|
+
request.headers.set('authorization', authorization);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (request_body && typeof request_body !== 'string') {
|
|
169
|
+
// TODO is this still necessary? we just bail out below
|
|
170
|
+
// per https://developer.mozilla.org/en-US/docs/Web/API/Request/Request, this can be a
|
|
171
|
+
// Blob, BufferSource, FormData, URLSearchParams, USVString, or ReadableStream object.
|
|
172
|
+
// non-string bodies are irksome to deal with, but luckily aren't particularly useful
|
|
173
|
+
// in this context anyway, so we take the easy route and ban them
|
|
174
|
+
throw new Error('Request body must be a string');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
response = await respond(request, options, {
|
|
178
|
+
prerender_default,
|
|
179
|
+
...state,
|
|
180
|
+
initiator: route
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
if (state.prerendering) {
|
|
184
|
+
dependency = { response, body: null };
|
|
185
|
+
state.prerendering.dependencies.set(url.pathname, dependency);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const set_cookie = response.headers.get('set-cookie');
|
|
189
|
+
if (set_cookie) {
|
|
190
|
+
set_cookies.push(
|
|
191
|
+
...set_cookie_parser.splitCookiesString(set_cookie).map((str) => {
|
|
192
|
+
const { name, value, ...options } = set_cookie_parser.parseString(str);
|
|
193
|
+
// options.sameSite is string, something more specific is required - type cast is safe
|
|
194
|
+
return /** @type{import('./types').Cookie} */ ({ name, value, options });
|
|
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 | 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
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (dependency) {
|
|
247
|
+
dependency.body = body;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return body;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (key === 'arrayBuffer') {
|
|
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);
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
return proxy;
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
return { fetcher, fetched, cookies: set_cookies };
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* @param {RequestInfo | URL} info
|
|
292
|
+
* @param {RequestInit | undefined} init
|
|
293
|
+
* @param {URL} url
|
|
294
|
+
*/
|
|
295
|
+
function normalize_fetch_input(info, init, url) {
|
|
296
|
+
if (info instanceof Request) {
|
|
297
|
+
return info;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return new Request(typeof info === 'string' ? new URL(info, url) : info, init);
|
|
301
|
+
}
|