Sveltekit的`handleFetch`仅在完整页面重新加载时正确拦截fetch调用。

huangapple go评论59阅读模式
英文:

Sveltekit's handleFetch in hooks only properly intercepts fetch call upon full page reload

问题

我正在使用Sveltekit的handleFetch类型来拦截任何fetch请求以设置Authorization头部。它在完整页面重新加载时正常工作(例如,通过按下F5或导航到使用授权的页面并在url栏中输入它)。但是,它不适用于a hrefredirect或不刷新整个页面的初始加载。奇怪的是,hooks.server.ts中的代码被执行,并且头部被正确设置,因为我可以看到console.log语句。此外,在失败的尝试之后(例如通过a hrefredirect),需要进行完整页面重新加载,以使任何其他页面再次正确加载。

我做错了什么?

hooks.server.ts

import { redirect, type HandleFetch } from "@sveltejs/kit";

export const handleFetch = (async ({ event, request, fetch }) => {
    if (request.url.startsWith('http://')) {
        request.headers.set('Authorization', `Bearer ${event.cookies.get('access_token')}`)
    }
    // This logs to the console properly
    console.log("Modified fetch request")
    console.log(request.headers);

    return fetch(request);
}) satisfies HandleFetch;

route文件夹中的page.ts

import type { PageLoad } from './$types';

export const load: PageLoad = async ({ fetch }) => {
    const response = await fetch('http://127.0.0.1:8080/api/v1/fetch_accounts', {
        method: 'GET',
        credentials: 'include'
    });

    let content = await response.json();

    return { content };
};
英文:

I am using Sveltekit's handleFetch type to intercept any fetch request to set an Authorization header. It works as intended on full page reloads (e.g., by pressing F5 or navigating to the a page that uses authorization via typing it in the url bar).
However, it does not work via a href, redirect or on an initial load that does not refresh the entire page. Strangely enough, the code in hooks.server.ts is executed and the header is set properly as I can see the console.log statements.
Also, after a failed attempt (i.e. via a href or redirect), a full page reload is necessary for any other page to load properly again.

What am I doing wrong?

hooks.server.ts

import {redirect, type HandleFetch } from "@sveltejs/kit"

export const handleFetch = (async ({ event, request, fetch }) => {
    if (request.url.startsWith('http://')) {
        request.headers.set('Authorization', `Bearer ${event.cookies.get('access_token')}`)
    }
    // This logs to the console properly
    console.log("Modified fetch request")
    console.log(request.headers);

    return fetch(request);
}) satisfies HandleFetch;

page.ts in the route folder:

import type { PageLoad } from './$types';

export const load: PageLoad = async ({ fetch, }) => {
	const response = await fetch('http://127.0.0.1:8080/api/v1/fetch_accounts', {
		method: 'GET',
		credentials: 'include'
	});

	let content = await response.json();

	return { content };
};

答案1

得分: 2

handleFetch仅在服务器上运行的fetch中运行(来自文档)

此函数允许您修改(或替换)在服务器上运行的load或action函数内发生的fetch请求(或在预渲染期间发生的请求)。

+page.ts中的load函数仅在第一次请求时在服务器上运行,但对于后续导航,它在客户端上运行(可以将其视为一旦在浏览器上就像是单页面应用程序)。

一个可能的解决方案是将load移至+page.server.ts,这个load函数将始终在服务器上运行。另一个选择是通过+server.js路由代理您的请求。

英文:

handleFetch only runs for fetches run on the server

(from the docs)

> This function allows you to modify (or replace) a fetch request that happens inside a load or action function that runs on the server (or during pre-rendering).

the load function in +page.ts runs on the server for the first request, but runs on the client for subsequent navigation (think of this as if once you are on the browser you are in a single page application).

A possible solution is to move the load to +page.server.ts, this load function will always runs on the server instead.
Another option is to proxy your request via a +server.js route.

huangapple
  • 本文由 发表于 2023年6月5日 00:33:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/76401400.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定