Skip to content

Commit

Permalink
merge
Browse files Browse the repository at this point in the history
  • Loading branch information
Rich-Harris committed Oct 28, 2022
2 parents b111acd + 004e81b commit 49b5171
Show file tree
Hide file tree
Showing 48 changed files with 314 additions and 158 deletions.
5 changes: 5 additions & 0 deletions .changeset/eighty-turkeys-exercise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

[fix] harmonize cookie path and add dev time warnings
5 changes: 5 additions & 0 deletions .changeset/lucky-moles-count.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@sveltejs/kit": patch
---

Restore `req.url` to `req.originalUrl` in dev and preview
3 changes: 3 additions & 0 deletions .changeset/pre.json
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@
"eighty-candles-grow",
"eighty-carrots-heal",
"eighty-parrots-cry",
"eighty-turkeys-exercise",
"eighty-waves-obey",
"eleven-buckets-deny",
"eleven-bugs-fail",
Expand Down Expand Up @@ -648,6 +649,7 @@
"lucky-bottles-kick",
"lucky-glasses-sell",
"lucky-guests-act",
"lucky-moles-count",
"lucky-phones-march",
"lucky-plums-listen",
"many-cups-report",
Expand Down Expand Up @@ -1292,6 +1294,7 @@
"tidy-rocks-beg",
"tidy-turkeys-rule",
"tidy-wasps-shave",
"tidy-wombats-repeat",
"tiny-badgers-love",
"tiny-candles-repeat",
"tiny-eels-hear",
Expand Down
5 changes: 5 additions & 0 deletions .changeset/tidy-wombats-repeat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': patch
---

[feat] add invalidateAll option to goto
2 changes: 2 additions & 0 deletions documentation/docs/20-core-concepts/20-load.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@ export async function load({ cookies }) {
}
```

> When setting cookies, be aware of the `path` property. By default, the `path` of a cookie is the current pathname. If you for example set a cookie at page `admin/user`, the cookie will only be available within the `admin` pages by default. In most cases you likely want to set `path` to `'/'` to make the cookie available throughout your app.
Both server-only and shared `load` functions have access to a `setHeaders` function that, when running on the server, can set headers for the response. (When running in the browser, `setHeaders` has no effect.) This is useful if you want the page to be cached, for example:

```js
Expand Down
4 changes: 3 additions & 1 deletion documentation/docs/30-advanced/70-packaging.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ You can use SvelteKit to build apps as well as component libraries, using the `@

When you're creating an app, the contents of `src/routes` is the public-facing stuff; [`src/lib`](/docs/modules#$lib) contains your app's internal library.

A SvelteKit component library has the exact same structure as a SvelteKit app, except that `src/lib` is the public-facing bit. `src/routes` might be a documentation or demo site that accompanies the library, or it might just be a sandbox you use during development.
A component library has the exact same structure as a SvelteKit app, except that `src/lib` is the public-facing bit. `src/routes` might be a documentation or demo site that accompanies the library, or it might just be a sandbox you use during development.

Running the `svelte-package` command from `@sveltejs/package` will take the contents of `src/lib` and generate a `package` directory (which can be [configured](/docs/configuration#package)) containing the following:

Expand Down Expand Up @@ -38,6 +38,8 @@ declare module 'your-library/Foo.svelte';
import Foo from 'your-library/Foo.svelte';
```

> You should avoid using [SvelteKit-specific modules](/docs/modules) like `$app` in your packages unless you intend for them to only be consumable by other SvelteKit projects. E.g. rather than using `import { browser } from '$app/environment'` you could use [`import.meta.env.SSR`](https://vitejs.dev/guide/env-and-mode.html#env-variables) to make the library available to all Vite-based projects or better yet use [Node conditional exports](https://nodejs.org/api/packages.html#conditional-exports) to make it work for all bundlers. You may also wish to pass in things like the current URL or a navigation action as a prop rather than relying directly on `$app/stores`, `$app/navigation`, etc. Writing your app in this more generic fashion will also make it easier to setup tools for testing, UI demos and so on.
### Options

`svelte-package` accepts the following options:
Expand Down
2 changes: 1 addition & 1 deletion packages/adapter-static/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@
"svelte": "^3.52.0",
"typescript": "^4.8.4",
"uvu": "^0.5.6",
"vite": "^3.1.8"
"vite": "^3.2.1"
}
}
2 changes: 1 addition & 1 deletion packages/adapter-static/test/apps/prerendered/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"devDependencies": {
"@sveltejs/kit": "workspace:*",
"svelte": "^3.52.0",
"vite": "^3.1.8"
"vite": "^3.2.1"
},
"type": "module"
}
2 changes: 1 addition & 1 deletion packages/adapter-static/test/apps/spa/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"@sveltejs/kit": "workspace:*",
"sirv-cli": "^2.0.2",
"svelte": "^3.52.0",
"vite": "^3.1.8"
"vite": "^3.2.1"
},
"type": "module"
}
2 changes: 1 addition & 1 deletion packages/create-svelte/templates/default/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"svelte": "^3.52.0",
"svelte-preprocess": "^4.10.7",
"typescript": "^4.8.4",
"vite": "^3.1.8"
"vite": "^3.2.1"
},
"type": "module",
"dependencies": {
Expand Down
14 changes: 14 additions & 0 deletions packages/kit/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# @sveltejs/kit

## 1.0.0-next.528

### Patch Changes

- Restore `req.url` to `req.originalUrl` in dev and preview ([#7343](https://github.com/sveltejs/kit/pull/7343))

## 1.0.0-next.527

### Patch Changes

- [fix] harmonize cookie path and add dev time warnings ([#7416](https://github.com/sveltejs/kit/pull/7416))

* [feat] add invalidateAll option to goto ([#7407](https://github.com/sveltejs/kit/pull/7407))

## 1.0.0-next.526

### Patch Changes
Expand Down
4 changes: 2 additions & 2 deletions packages/kit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@sveltejs/kit",
"version": "1.0.0-next.526",
"version": "1.0.0-next.528",
"repository": {
"type": "git",
"url": "https://github.com/sveltejs/kit",
Expand Down Expand Up @@ -37,7 +37,7 @@
"svelte-preprocess": "^4.10.7",
"typescript": "^4.8.4",
"uvu": "^0.5.6",
"vite": "^3.1.8"
"vite": "^3.2.1"
},
"peerDependencies": {
"svelte": "^3.44.0",
Expand Down
2 changes: 0 additions & 2 deletions packages/kit/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,3 @@
export const SVELTE_KIT_ASSETS = '/_svelte_kit_assets';

export const GENERATED_COMMENT = '// this file is generated — do not edit it\n';

export const DATA_SUFFIX = '/__data.json';
2 changes: 2 additions & 0 deletions packages/kit/src/exports/vite/dev/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,8 @@ export async function dev(vite, vite_config, svelte_config) {
remove_static_middlewares(vite.middlewares);

vite.middlewares.use(async (req, res) => {
// Vite's base middleware strips out the base path. Restore it
req.url = req.originalUrl;
try {
const base = `${vite.config.server.https ? 'https' : 'http'}://${
req.headers[':authority'] || req.headers.host
Expand Down
23 changes: 16 additions & 7 deletions packages/kit/src/runtime/client/client.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { onMount, tick } from 'svelte';
import { make_trackable, decode_params, normalize_path } from '../../utils/url.js';
import { make_trackable, decode_params, normalize_path, add_data_suffix } from '../../utils/url.js';
import { find_anchor, get_base_uri, scroll_state } from './utils.js';
import {
lock_fetch,
Expand All @@ -14,7 +14,6 @@ import Root from '__GENERATED__/root.svelte';
import { nodes, server_loads, dictionary, matchers, hooks } from '__GENERATED__/client-manifest.js';
import { HttpError, Redirect } from '../control.js';
import { stores } from './singletons.js';
import { DATA_SUFFIX } from '../../constants.js';
import { unwrap_promises } from '../../utils/promises.js';
import * as devalue from 'devalue';

Expand Down Expand Up @@ -164,13 +163,19 @@ export function create_client({ target, base, trailing_slash }) {

/**
* @param {string | URL} url
* @param {{ noscroll?: boolean; replaceState?: boolean; keepfocus?: boolean; state?: any }} opts
* @param {{ noscroll?: boolean; replaceState?: boolean; keepfocus?: boolean; state?: any; invalidateAll?: boolean }} opts
* @param {string[]} redirect_chain
* @param {{}} [nav_token]
*/
async function goto(
url,
{ noscroll = false, replaceState = false, keepfocus = false, state = {} },
{
noscroll = false,
replaceState = false,
keepfocus = false,
state = {},
invalidateAll = false
},
redirect_chain,
nav_token
) {
Expand All @@ -188,7 +193,11 @@ export function create_client({ target, base, trailing_slash }) {
replaceState
},
nav_token,
accepted: () => {},
accepted: () => {
if (invalidateAll) {
force_invalidation = true;
}
},
blocked: () => {},
type: 'goto'
});
Expand Down Expand Up @@ -1212,7 +1221,7 @@ export function create_client({ target, base, trailing_slash }) {
post_update();
}
} else if (result.type === 'redirect') {
goto(result.location, {}, []);
goto(result.location, { invalidateAll: true }, []);
} else {
/** @type {Record<string, any>} */
const props = {
Expand Down Expand Up @@ -1501,7 +1510,7 @@ export function create_client({ target, base, trailing_slash }) {
*/
async function load_data(url, invalid) {
const data_url = new URL(url);
data_url.pathname = url.pathname.replace(/\/$/, '') + DATA_SUFFIX;
data_url.pathname = add_data_suffix(url.pathname);

const res = await native_fetch(data_url.href, {
headers: {
Expand Down
67 changes: 55 additions & 12 deletions packages/kit/src/runtime/server/cookie.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
import { parse, serialize } from 'cookie';
import { has_data_suffix, normalize_path, strip_data_suffix } from '../../utils/url.js';

/**
* Tracks all cookies set during dev mode so we can emit warnings
* when we detect that there's likely cookie misusage due to wrong paths
*
* @type {Record<string, Set<string>>} */
const cookie_paths = {};

/**
* @param {Request} request
* @param {URL} url
* @param {Pick<import('types').SSROptions, 'dev' | 'trailing_slash'>} options
*/
export function get_cookies(request, url) {
export function get_cookies(request, url, options) {
const header = request.headers.get('cookie') ?? '';

const initial_cookies = parse(header);
Expand Down Expand Up @@ -42,7 +51,17 @@ export function get_cookies(request, url) {

const decode = opts?.decode || decodeURIComponent;
const req_cookies = parse(header, { decode });
return req_cookies[name]; // the decoded string or undefined
const cookie = req_cookies[name]; // the decoded string or undefined

if (!options.dev || cookie) {
return cookie;
}

if (c || cookie_paths[name]?.size > 0) {
console.warn(
`Cookie with name '${name}' was not found, but a cookie with that name exists at a sub path. Did you mean to set its 'path' to '/'?`
);
}
},

/**
Expand All @@ -51,30 +70,54 @@ export function get_cookies(request, url) {
* @param {import('cookie').CookieSerializeOptions} opts
*/
set(name, value, opts = {}) {
let path = opts.path;
if (!path) {
const normalized = normalize_path(
// Remove suffix: 'foo/__data.json' would mean the cookie path is '/foo',
// whereas a direct hit of /foo would mean the cookie path is '/'
has_data_suffix(url.pathname) ? strip_data_suffix(url.pathname) : url.pathname,
options.trailing_slash
);
// Emulate browser-behavior: if the cookie is set at '/foo/bar', its path is '/foo'
path = normalized.split('/').slice(0, -1).join('/') || '/';
}

new_cookies[name] = {
name,
value,
options: {
...defaults,
...opts
...opts,
path
}
};

if (options.dev) {
cookie_paths[name] = cookie_paths[name] || new Set();
if (!value) {
if (!cookie_paths[name].has(path) && cookie_paths[name].size > 0) {
console.warn(
`Trying to delete cookie '${name}' at path '${path}', but a cookie with that name only exists at a different path.`
);
}
cookie_paths[name].delete(path);
} else {
// We could also emit a warning here if the cookie already exists at a different path,
// but that's more likely a false positive because it's valid to set the same name at different paths
cookie_paths[name].add(path);
}
}
},

/**
* @param {string} name
* @param {import('cookie').CookieSerializeOptions} opts
*/
delete(name, opts = {}) {
new_cookies[name] = {
name,
value: '',
options: {
...defaults,
...opts,
maxAge: 0
}
};
cookies.set(name, '', {
...opts,
maxAge: 0
});
},

/**
Expand Down
24 changes: 17 additions & 7 deletions packages/kit/src/runtime/server/cookie.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,15 @@ paths.negative.forEach(([path, constraint]) => {
});
});

/** @param {boolean} localhost */
const cookies_setup = (localhost = false) => {
const url = new URL(localhost ? 'http://localhost:1234' : 'https://example.com');
/** @param {string} href */
const cookies_setup = (href = 'https://example.com') => {
const url = new URL(href);
const request = new Request(url, {
headers: new Headers({
cookie: 'a=b;'
})
});
return get_cookies(request, url);
return get_cookies(request, url, { dev: false, trailing_slash: 'ignore' });
};

test('a cookie should not be present after it is deleted', () => {
Expand All @@ -67,12 +67,22 @@ test('default values when set is called', () => {
const opts = new_cookies['a']?.options;
assert.equal(opts?.secure, true);
assert.equal(opts?.httpOnly, true);
assert.equal(opts?.path, undefined);
assert.equal(opts?.path, '/');
assert.equal(opts?.sameSite, 'lax');
});

test('default values when set is called on sub path', () => {
const { cookies, new_cookies } = cookies_setup('https://example.com/foo/bar');
cookies.set('a', 'b');
const opts = new_cookies['a']?.options;
assert.equal(opts?.secure, true);
assert.equal(opts?.httpOnly, true);
assert.equal(opts?.path, '/foo');
assert.equal(opts?.sameSite, 'lax');
});

test('default values when on localhost', () => {
const { cookies, new_cookies } = cookies_setup(true);
const { cookies, new_cookies } = cookies_setup('http://localhost:1234');
cookies.set('a', 'b');
const opts = new_cookies['a']?.options;
assert.equal(opts?.secure, false);
Expand All @@ -94,7 +104,7 @@ test('default values when delete is called', () => {
const opts = new_cookies['a']?.options;
assert.equal(opts?.secure, true);
assert.equal(opts?.httpOnly, true);
assert.equal(opts?.path, undefined);
assert.equal(opts?.path, '/');
assert.equal(opts?.sameSite, 'lax');
assert.equal(opts?.maxAge, 0);
});
Expand Down
Loading

0 comments on commit 49b5171

Please sign in to comment.