From be2c8a870e88c5eaa293ac492e49ca8bd2c6037d Mon Sep 17 00:00:00 2001 From: Thomas Alton Date: Wed, 11 Oct 2023 14:08:50 -0500 Subject: [PATCH] fix: follow whatwg fetch spec for handling redirect loops (#10857) --- .changeset/proud-worms-press.md | 5 ++++ packages/kit/src/runtime/client/client.js | 32 ++++++++++------------- 2 files changed, 19 insertions(+), 18 deletions(-) create mode 100644 .changeset/proud-worms-press.md diff --git a/.changeset/proud-worms-press.md b/.changeset/proud-worms-press.md new file mode 100644 index 000000000000..9a4f3564476f --- /dev/null +++ b/.changeset/proud-worms-press.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/kit': patch +--- + +fix: follow whatwg fetch spec for handling redirect loops diff --git a/packages/kit/src/runtime/client/client.js b/packages/kit/src/runtime/client/client.js index f788b8b917e6..6c7e723c71e7 100644 --- a/packages/kit/src/runtime/client/client.js +++ b/packages/kit/src/runtime/client/client.js @@ -173,7 +173,7 @@ export function create_client(app, target) { if (navigation_result) { if (navigation_result.type === 'redirect') { - return goto(new URL(navigation_result.location, url).href, {}, [url.pathname], nav_token); + return goto(new URL(navigation_result.location, url).href, {}, 1, nav_token); } else { if (navigation_result.props.page !== undefined) { page = navigation_result.props.page; @@ -208,7 +208,7 @@ export function create_client(app, target) { /** * @param {string | URL} url * @param {{ noScroll?: boolean; replaceState?: boolean; keepFocus?: boolean; state?: any; invalidateAll?: boolean }} opts - * @param {string[]} redirect_chain + * @param {number} redirect_count * @param {{}} [nav_token] */ async function goto( @@ -220,7 +220,7 @@ export function create_client(app, target) { state = {}, invalidateAll = false }, - redirect_chain, + redirect_count, nav_token ) { if (typeof url === 'string') { @@ -231,7 +231,7 @@ export function create_client(app, target) { url, scroll: noScroll ? scroll_state() : null, keepfocus: keepFocus, - redirect_chain, + redirect_count, details: { state, replaceState @@ -941,7 +941,7 @@ export function create_client(app, target) { * url: URL; * scroll: { x: number, y: number } | null; * keepfocus: boolean; - * redirect_chain: string[]; + * redirect_count: number; * details: { * replaceState: boolean; * state: any; @@ -957,7 +957,7 @@ export function create_client(app, target) { url, scroll, keepfocus, - redirect_chain, + redirect_count, details, type, delta, @@ -1014,7 +1014,8 @@ export function create_client(app, target) { } if (navigation_result.type === 'redirect') { - if (redirect_chain.length > 10 || redirect_chain.includes(url.pathname)) { + // whatwg fetch spec https://fetch.spec.whatwg.org/#http-redirect-fetch says to error after 20 redirects + if (redirect_count >= 20) { navigation_result = await load_root_error_page({ status: 500, error: await handle_error(new Error('Redirect loop'), { @@ -1026,12 +1027,7 @@ export function create_client(app, target) { route: { id: null } }); } else { - goto( - new URL(navigation_result.location, url).href, - {}, - [...redirect_chain, url.pathname], - nav_token - ); + goto(new URL(navigation_result.location, url).href, {}, redirect_count + 1, nav_token); return false; } } else if (/** @type {number} */ (navigation_result.props.page?.status) >= 400) { @@ -1379,7 +1375,7 @@ export function create_client(app, target) { }, goto: (href, opts = {}) => { - return goto(href, opts, []); + return goto(href, opts, 0); }, invalidate: (resource) => { @@ -1440,7 +1436,7 @@ export function create_client(app, target) { tick().then(reset_focus); } } else if (result.type === 'redirect') { - goto(result.location, { invalidateAll: true }, []); + goto(result.location, { invalidateAll: true }, 0); } else { /** @type {Record} */ root.$set({ @@ -1595,7 +1591,7 @@ export function create_client(app, target) { url, scroll: options.noscroll ? scroll_state() : null, keepfocus: options.keep_focus ?? false, - redirect_chain: [], + redirect_count: 0, details: { state: {}, replaceState: options.replace_state ?? url.href === location.href @@ -1649,7 +1645,7 @@ export function create_client(app, target) { url, scroll: noscroll ? scroll_state() : null, keepfocus: keep_focus ?? false, - redirect_chain: [], + redirect_count: 0, details: { state: {}, replaceState: replace_state ?? url.href === location.href @@ -1687,7 +1683,7 @@ export function create_client(app, target) { url, scroll, keepfocus: false, - redirect_chain: [], + redirect_count: 0, details: null, accepted: () => { current_history_index = event.state[INDEX_KEY];