Repository: sveltejs/kit (js)

Issue:
Returning location from POST does not set 3xx status code
### Describe the bug

When returning a `location` path from a `+page.server.ts` sveltekit set status as 200, and does not perform a redirect.

The problem is located in `packages/kit/src/runtime/server/page/index.js` at 81:38

```ts
return redirect_response(status, result.location);
```

where status is not changed from 200 (at 57:5)

```ts
let status = 200;
```

I'd be willing to submit a PR to fix this issue.

### Reproduction

https://stackblitz.com/edit/sveltejs-kit-template-default-t26lrz?file=src/routes/+page.svelte

The page contains two buttons:
- Submit form with `throw redirect()`
- Submit form with `location`

### Logs

_No response_

### System Info

```shell
System:
    OS: macOS 12.5
    CPU: (10) arm64 Apple M1 Pro
    Memory: 69.66 MB / 16.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 18.7.0 - ~/.nvm/versions/node/v18.7.0/bin/node
    npm: 8.15.0 - ~/.nvm/versions/node/v18.7.0/bin/npm
  Browsers:
    Firefox Developer Edition: 104.0
    Safari: 15.6
  npmPackages:
    @sveltejs/adapter-auto: next => 1.0.0-next.64 
    @sveltejs/adapter-node: 1.0.0-next.86 => 1.0.0-next.86 
    @sveltejs/kit: 1.0.0-next.415 => 1.0.0-next.415 
    svelte: ^3.49.0 => 3.49.0 
    vite: ^3.0.8 => 3.0.8
```


### Severity

annoyance

### Additional Information

_No response_

Pull request:
[fix] set `status` to 303 when POST provides a `location`
Closes #5976

Sets status to 303 when a POST handler returns a location.


### Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
- [x] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
- [x] This message body should clearly illustrate what problems it solves.
- [ ] Ideally, include a test that fails without this PR but passes with it.

### Tests
- [x] Run the tests with `pnpm test` and lint the project with `pnpm lint` and `pnpm check`

### Changesets
- [x] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpm changeset` and following the prompts. All changesets should be `patch` until SvelteKit 1.0


Patch:
diff --git a/.changeset/gentle-news-shout.md b/.changeset/gentle-news-shout.md
new file mode 100644
index 000000000..c5a3bcfda
--- /dev/null
+++ b/.changeset/gentle-news-shout.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+Return a 303 response when a `POST` handler provides a `location`
diff --git a/.changeset/pre.json b/.changeset/pre.json
index c213a107d..1dce3f4af 100644
--- a/.changeset/pre.json
+++ b/.changeset/pre.json
@@ -30,7 +30,8 @@
     "prerendering-test-disabled": "0.0.2-next.0",
     "test-writes": "0.0.2-next.0",
     "svelte-migrate": "1.0.0-next.0",
-    "skeleton-template": "0.0.1-next.0"
+    "skeleton-template": "0.0.1-next.0",
+    "@sveltejs/package": "1.0.0-next.1"
   },
   "changesets": [
     "afraid-eels-tease",
@@ -122,6 +123,7 @@
     "chilled-moons-sniff",
     "chilled-rivers-talk",
     "chilled-starfishes-jog",
+    "chilled-years-smash",
     "chilled-zebras-check",
     "chilly-cars-battle",
     "chilly-files-greet",
@@ -574,6 +576,7 @@
     "nasty-llamas-lay",
     "nasty-seahorses-know",
     "nasty-seas-reflect",
+    "nasty-shoes-mate",
     "nasty-trees-cheer",
     "nasty-waves-kneel",
     "neat-cups-begin",
@@ -899,6 +902,7 @@
     "soft-months-fail",
     "soft-news-teach",
     "soft-students-cover",
+    "sour-cherries-play",
     "sour-hounds-punch",
     "sour-needles-compete",
     "sour-penguins-admire",
diff --git a/.changeset/wicked-spoons-leave.md b/.changeset/wicked-spoons-leave.md
new file mode 100644
index 000000000..b83f016ce
--- /dev/null
+++ b/.changeset/wicked-spoons-leave.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+Use relative asset paths where possible
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ef527cd88..9f5643fa9 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -48,6 +48,7 @@ You may need to install some dependencies first, e.g. with `npx playwright insta
 If there are tests that fail on the CI, you can retrieve the failed screenshots by going to the summary page of the CI run. You can usually find this by clicking on "Details" of the check results, click "Summary" at the top-left corner, and then scroll to the bottom "Artifacts" section to download the archive.
 
 It is very easy to introduce flakiness in a browser test. If you try to fix the flakiness in a test, you can run it until failure to gain some confidence you've fixed the test with a command like:
+
 ```
 npx playwright test --workers=1 --repeat-each 1000 --max-failures 1 -g "accepts a Request object"
 ```
@@ -60,7 +61,7 @@ If you would like to test local changes to Vite or another dependency, you can b
 {
 	// ...
 	"dependencies": {
-		"vite": "^2.0.0"
+		"vite": "^3.0.0"
 	},
 	"pnpm": {
 		"overrides": {
diff --git a/packages/create-svelte/CHANGELOG.md b/packages/create-svelte/CHANGELOG.md
index 883a08dbd..dbdb840a5 100644
--- a/packages/create-svelte/CHANGELOG.md
+++ b/packages/create-svelte/CHANGELOG.md
@@ -1,5 +1,11 @@
 # create-svelte
 
+## 2.0.0-next.155
+
+### Patch Changes
+
+- make variable names more descriptive ([#5983](https://github.com/sveltejs/kit/pull/5983))
+
 ## 2.0.0-next.154
 
 ### Patch Changes
diff --git a/packages/create-svelte/package.json b/packages/create-svelte/package.json
index b077ed77e..ca8f89dce 100644
--- a/packages/create-svelte/package.json
+++ b/packages/create-svelte/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "create-svelte",
-	"version": "2.0.0-next.154",
+	"version": "2.0.0-next.155",
 	"repository": {
 		"type": "git",
 		"url": "https://github.com/sveltejs/kit",
diff --git a/packages/create-svelte/templates/default/package.json b/packages/create-svelte/templates/default/package.json
index bf0689242..ce127a154 100644
--- a/packages/create-svelte/templates/default/package.json
+++ b/packages/create-svelte/templates/default/package.json
@@ -13,7 +13,7 @@
 		"svelte": "^3.48.0",
 		"svelte-preprocess": "^4.10.6",
 		"typescript": "^4.7.4",
-		"vite": "^3.0.0"
+		"vite": "^3.0.4"
 	},
 	"type": "module",
 	"dependencies": {
diff --git a/packages/create-svelte/templates/default/package.template.json b/packages/create-svelte/templates/default/package.template.json
index 3e51b6a62..d4cc74df2 100644
--- a/packages/create-svelte/templates/default/package.template.json
+++ b/packages/create-svelte/templates/default/package.template.json
@@ -11,7 +11,7 @@
 		"@sveltejs/adapter-auto": "next",
 		"@sveltejs/kit": "next",
 		"svelte": "^3.46.0",
-		"vite": "^3.0.0"
+		"vite": "^3.0.4"
 	},
 	"type": "module",
 	"dependencies": {
diff --git a/packages/create-svelte/templates/skeleton/package.template.json b/packages/create-svelte/templates/skeleton/package.template.json
index 9b213b5b1..0d2623c4e 100644
--- a/packages/create-svelte/templates/skeleton/package.template.json
+++ b/packages/create-svelte/templates/skeleton/package.template.json
@@ -11,7 +11,7 @@
 		"@sveltejs/adapter-auto": "workspace:*",
 		"@sveltejs/kit": "workspace:*",
 		"svelte": "^3.44.0",
-		"vite": "^3.0.0"
+		"vite": "^3.0.4"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/CHANGELOG.md b/packages/kit/CHANGELOG.md
index b5c4c0dc5..ec4774ada 100644
--- a/packages/kit/CHANGELOG.md
+++ b/packages/kit/CHANGELOG.md
@@ -1,5 +1,13 @@
 # @sveltejs/kit
 
+## 1.0.0-next.418
+
+### Patch Changes
+
+- Prevent double import of env modules ([#5955](https://github.com/sveltejs/kit/pull/5955))
+
+* Tighten up params typings, fix load function typings, add event typings to generated types ([#5974](https://github.com/sveltejs/kit/pull/5974))
+
 ## 1.0.0-next.417
 
 ### Patch Changes
diff --git a/packages/kit/package.json b/packages/kit/package.json
index 89891f151..ce4d052af 100644
--- a/packages/kit/package.json
+++ b/packages/kit/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "@sveltejs/kit",
-	"version": "1.0.0-next.417",
+	"version": "1.0.0-next.418",
 	"repository": {
 		"type": "git",
 		"url": "https://github.com/sveltejs/kit",
diff --git a/packages/kit/src/runtime/server/page/index.js b/packages/kit/src/runtime/server/page/index.js
index 9840a417c..9a1769bb0 100644
--- a/packages/kit/src/runtime/server/page/index.js
+++ b/packages/kit/src/runtime/server/page/index.js
@@ -77,7 +77,7 @@ export async function render_page(event, route, options, state, resolve_opts) {
 					}
 
 					if (event.request.method === 'POST' && result?.location) {
-						return redirect_response(status, result.location);
+						return redirect_response(303, result.location);
 					}
 				} else {
 					event.setHeaders({
diff --git a/packages/kit/src/runtime/server/page/render.js b/packages/kit/src/runtime/server/page/render.js
index 31d9f494a..019229d13 100644
--- a/packages/kit/src/runtime/server/page/render.js
+++ b/packages/kit/src/runtime/server/page/render.js
@@ -150,9 +150,31 @@ export async function render_response({
 
 	const target = hash(body);
 
+	/**
+	 * The prefix to use for static assets. Replaces `%sveltekit.assets%` in the template
+	 * @type {string}
+	 */
+	let assets;
+
+	if (options.paths.assets) {
+		// if an asset path is specified, use it
+		assets = options.paths.assets;
+	} else if (state.prerendering?.fallback) {
+		// if we're creating a fallback page, asset paths need to be root-relative
+		assets = options.paths.base;
+	} else {
+		// otherwise we want asset paths to be relative to the page, so that they
+		// will work in odd contexts like IPFS, the internet archive, and so on
+		const segments = event.url.pathname.slice(options.paths.base.length).split('/').slice(2);
+		assets = segments.length > 0 ? segments.map(() => '..').join('/') : '.';
+	}
+
+	/** @param {string} path */
+	const prefixed = (path) => (path.startsWith('/') ? path : `${assets}/${path}`);
+
 	// prettier-ignore
 	const init_app = `
-		import { set_public_env, start } from ${s(options.prefix + entry.file)};
+		import { set_public_env, start } from ${s(prefixed(entry.file))};
 
 		set_public_env(${s(options.public_env)});
 
@@ -195,7 +217,7 @@ export async function render_response({
 	}
 
 	for (const dep of stylesheets) {
-		const path = options.prefix + dep;
+		const path = prefixed(dep);
 		const attributes = [];
 
 		if (csp.style_needs_nonce) {
@@ -217,7 +239,7 @@ export async function render_response({
 
 	if (page_config.router || page_config.hydrate) {
 		for (const dep of modulepreloads) {
-			const path = options.prefix + dep;
+			const path = prefixed(dep);
 			link_header_preloads.add(`<${encodeURI(path)}>; rel="modulepreload"; nopush`);
 			if (state.prerendering) {
 				head += `\n\t<link rel="modulepreload" href="${path}">`;
@@ -292,10 +314,6 @@ export async function render_response({
 		}
 	}
 
-	const segments = event.url.pathname.slice(options.paths.base.length).split('/').slice(2);
-	const assets =
-		options.paths.assets || (segments.length > 0 ? segments.map(() => '..').join('/') : '.');
-
 	// TODO flush chunks as early as we can
 	const html =
 		(await resolve_opts.transformPageChunk({
diff --git a/packages/kit/src/vite/build/build_server.js b/packages/kit/src/vite/build/build_server.js
index e0a778c5f..7414463b8 100644
--- a/packages/kit/src/vite/build/build_server.js
+++ b/packages/kit/src/vite/build/build_server.js
@@ -69,7 +69,6 @@ export class Server {
 			manifest,
 			method_override: ${s(config.kit.methodOverride)},
 			paths: { base, assets },
-			prefix: assets + '/',
 			prerender: {
 				default: ${config.kit.prerender.default},
 				enabled: ${config.kit.prerender.enabled}
diff --git a/packages/kit/src/vite/build/utils.js b/packages/kit/src/vite/build/utils.js
index 35cdc330a..a1b3da9f8 100644
--- a/packages/kit/src/vite/build/utils.js
+++ b/packages/kit/src/vite/build/utils.js
@@ -88,9 +88,11 @@ export function find_deps(manifest, entry, add_dynamic_css) {
  * @return {import('vite').UserConfig}
  */
 export const get_default_config = function ({ config, input, ssr, outDir }) {
+	const prefix = `${config.kit.appDir}/immutable`;
+
 	return {
 		appType: 'custom',
-		base: assets_base(config.kit),
+		base: ssr ? assets_base(config.kit) : './',
 		build: {
 			cssCodeSplit: true,
 			// don't use the default name to avoid collisions with 'static/manifest.json'
@@ -101,11 +103,9 @@ export const get_default_config = function ({ config, input, ssr, outDir }) {
 				input,
 				output: {
 					format: 'esm',
-					entryFileNames: ssr ? '[name].js' : `${config.kit.appDir}/immutable/[name]-[hash].js`,
-					chunkFileNames: ssr
-						? 'chunks/[name].js'
-						: `${config.kit.appDir}/immutable/chunks/[name]-[hash].js`,
-					assetFileNames: `${config.kit.appDir}/immutable/assets/[name]-[hash][extname]`
+					entryFileNames: ssr ? '[name].js' : `${prefix}/[name]-[hash].js`,
+					chunkFileNames: ssr ? 'chunks/[name].js' : `${prefix}/chunks/[name]-[hash].js`,
+					assetFileNames: `${prefix}/assets/[name]-[hash][extname]`
 				},
 				preserveEntrySignatures: 'strict'
 			},
@@ -125,6 +125,14 @@ export const get_default_config = function ({ config, input, ssr, outDir }) {
 		},
 		ssr: {
 			noExternal: ['@sveltejs/kit']
+		},
+		worker: {
+			rollupOptions: {
+				output: {
+					entryFileNames: `${prefix}/workers/[name]-[hash].js`,
+					chunkFileNames: `${prefix}/workers/chunks/[name]-[hash].js`
+				}
+			}
 		}
 	};
 };
@@ -134,11 +142,7 @@ export const get_default_config = function ({ config, input, ssr, outDir }) {
  * @returns {string}
  */
 export function assets_base(config) {
-	// TODO this is so that Vite's preloading works. Unfortunately, it fails
-	// during `svelte-kit preview`, because we use a local asset path. This
-	// may be fixed in Vite 3: https://github.com/vitejs/vite/issues/2009
-	const { base, assets } = config.paths;
-	return `${assets || base}/`;
+	return config.paths.assets || config.paths.base || './';
 }
 
 const method_names = new Set(['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH']);
diff --git a/packages/kit/src/vite/dev/index.js b/packages/kit/src/vite/dev/index.js
index 0c20b7a91..c67f11fe2 100644
--- a/packages/kit/src/vite/dev/index.js
+++ b/packages/kit/src/vite/dev/index.js
@@ -432,7 +432,6 @@ export async function dev(vite, vite_config, svelte_config, illegal_imports) {
 							base: svelte_config.kit.paths.base,
 							assets
 						},
-						prefix: '',
 						prerender: {
 							default: svelte_config.kit.prerender.default,
 							enabled: svelte_config.kit.prerender.enabled
diff --git a/packages/kit/src/vite/index.js b/packages/kit/src/vite/index.js
index 70a9cf482..a5ef0f32e 100644
--- a/packages/kit/src/vite/index.js
+++ b/packages/kit/src/vite/index.js
@@ -207,7 +207,7 @@ function kit() {
 			paths = {
 				build_dir: `${svelte_config.kit.outDir}/build`,
 				output_dir: `${svelte_config.kit.outDir}/output`,
-				client_out_dir: `${svelte_config.kit.outDir}/output/client/`
+				client_out_dir: `${svelte_config.kit.outDir}/output/client`
 			};
 
 			illegal_imports = new Set([
@@ -230,7 +230,7 @@ function kit() {
 			/** @type {import('vite').UserConfig} */
 			const result = {
 				appType: 'custom',
-				base: '/',
+				base: './',
 				build: {
 					rollupOptions: {
 						// Vite dependency crawler needs an explicit JS entry point
diff --git a/packages/kit/types/internal.d.ts b/packages/kit/types/internal.d.ts
index a9938d281..9738ab5a0 100644
--- a/packages/kit/types/internal.d.ts
+++ b/packages/kit/types/internal.d.ts
@@ -239,7 +239,6 @@ export interface SSROptions {
 		base: string;
 		assets: string;
 	};
-	prefix: string;
 	prerender: {
 		default: boolean;
 		enabled: boolean;
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d13023cd9..92e3c0431 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -247,7 +247,7 @@ importers:
       svelte: ^3.48.0
       svelte-preprocess: ^4.10.6
       typescript: ^4.7.4
-      vite: ^3.0.0
+      vite: ^3.0.4
     dependencies:
       '@fontsource/fira-mono': 4.5.8
       '@lukeed/uuid': 2.0.0
@@ -556,7 +556,7 @@ importers:
       shiki-twoslash: ^3.0.2
       svelte: ^3.48.0
       typescript: ^4.7.4
-      vite: ^3.0.0
+      vite: ^3.0.4
       vite-imagetools: ^4.0.3
     devDependencies:
       '@sveltejs/adapter-auto': link:../../packages/adapter-auto
diff --git a/sites/kit.svelte.dev/package.json b/sites/kit.svelte.dev/package.json
index 616f17709..5be7b5e44 100644
--- a/sites/kit.svelte.dev/package.json
+++ b/sites/kit.svelte.dev/package.json
@@ -21,7 +21,7 @@
 		"shiki-twoslash": "^3.0.2",
 		"svelte": "^3.48.0",
 		"typescript": "^4.7.4",
-		"vite": "^3.0.0",
+		"vite": "^3.0.4",
 		"vite-imagetools": "^4.0.3"
 	},
 	"type": "module"


Test patch:
diff --git a/packages/adapter-static/test/apps/spa/src/routes/fallback/[...rest]/+page.svelte b/packages/adapter-static/test/apps/spa/src/routes/fallback/[...rest]/+page.svelte
new file mode 100644
index 000000000..671b43ec7
--- /dev/null
+++ b/packages/adapter-static/test/apps/spa/src/routes/fallback/[...rest]/+page.svelte
@@ -0,0 +1,1 @@
+<h1>the fallback page was rendered</h1>
diff --git a/packages/adapter-static/test/test.js b/packages/adapter-static/test/test.js
index ffc1f4072..97bef6e5d 100644
--- a/packages/adapter-static/test/test.js
+++ b/packages/adapter-static/test/test.js
@@ -14,8 +14,11 @@ run('prerendered', (test) => {
 });
 
 run('spa', (test) => {
-	test('generates a fallback page', ({ cwd }) => {
+	test('generates a fallback page', async ({ base, cwd, page }) => {
 		assert.ok(fs.existsSync(`${cwd}/build/200.html`));
+
+		await page.goto(`${base}/fallback/a/b/c`);
+		assert.equal(await page.textContent('h1'), 'the fallback page was rendered');
 	});
 
 	test('does not prerender pages without prerender=true', ({ cwd }) => {
diff --git a/packages/kit/test/apps/basics/src/routes/shadowed/post-success-redirect/+page.server.js b/packages/kit/test/apps/basics/src/routes/shadowed/post-success-redirect/+page.server.js
new file mode 100644
index 000000000..30d0b0e3f
--- /dev/null
+++ b/packages/kit/test/apps/basics/src/routes/shadowed/post-success-redirect/+page.server.js
@@ -0,0 +1,5 @@
+export function POST() {
+	return {
+		location: '/shadowed/post-success-redirect/redirected'
+	};
+}
diff --git a/packages/kit/test/apps/basics/src/routes/shadowed/post-success-redirect/+page.svelte b/packages/kit/test/apps/basics/src/routes/shadowed/post-success-redirect/+page.svelte
new file mode 100644
index 000000000..74dca32e8
--- /dev/null
+++ b/packages/kit/test/apps/basics/src/routes/shadowed/post-success-redirect/+page.svelte
@@ -0,0 +1,3 @@
+<form method="POST">
+	<button>Click me</button>
+</form>
diff --git a/packages/kit/test/apps/basics/src/routes/shadowed/post-success-redirect/redirected/+page.svelte b/packages/kit/test/apps/basics/src/routes/shadowed/post-success-redirect/redirected/+page.svelte
new file mode 100644
index 000000000..6ba792f15
--- /dev/null
+++ b/packages/kit/test/apps/basics/src/routes/shadowed/post-success-redirect/redirected/+page.svelte
@@ -0,0 +1,1 @@
+<h1>POST was successful</h1>
diff --git a/packages/kit/test/apps/basics/test/test.js b/packages/kit/test/apps/basics/test/test.js
index d03fa9600..e54c9ec49 100644
--- a/packages/kit/test/apps/basics/test/test.js
+++ b/packages/kit/test/apps/basics/test/test.js
@@ -188,6 +188,12 @@ test.describe('Shadowed pages', () => {
 		);
 	});
 
+	test('Handles POST success with returned location', async ({ page }) => {
+		await page.goto('/shadowed/post-success-redirect');
+		await Promise.all([page.waitForNavigation(), page.click('button')]);
+		expect(await page.textContent('h1')).toBe('POST was successful');
+	});
+
 	test('Renders error page for 4xx and 5xx responses from GET', async ({ page, clicknav }) => {
 		await page.goto('/shadowed');
 		await clicknav('[href="/shadowed/error-get"]');