SvelteKit中hooks.server.ts如何读取请求体且避免报错?
在SvelteKit的hooks.server.ts中正确读取请求体的方法
当你直接调用request.body.getReader()读取流后,这个ReadableStream会被**锁定(locked: true)**且状态变为closed,后续任何尝试读取该流的操作(比如request.json())都会抛出"Body is unusable"错误——因为Fetch API的请求体流是一次性的,被读取消耗后就无法重复使用。
下面提供两种可靠的解决方案:
方案一:读取后重新构建Request对象
读取请求体内容后,基于原始请求创建新的Request实例,把读取到的内容重新作为body传入,让后续路由/中间件能正常读取请求体:
import type { Handle } from '@sveltejs/kit'; export const handle = (async ({ event, resolve }) => { // 仅针对有请求体的方法处理,比如POST/PUT if (['POST', 'PUT', 'PATCH'].includes(event.request.method)) { // 读取请求体文本 const bodyText = await event.request.text(); console.log('请求体内容:', bodyText); // 重新构建Request,保留原始请求的方法、头等信息 event.request = new Request(event.request, { body: bodyText, headers: event.request.headers }); } const response = await resolve(event); return response; }) satisfies Handle;
如果需要解析JSON:
import type { Handle } from '@sveltejs/kit'; export const handle = (async ({ event, resolve }) => { if (['POST', 'PUT', 'PATCH'].includes(event.request.method)) { const bodyText = await event.request.text(); const bodyData = JSON.parse(bodyText); console.log('解析后的请求体:', bodyData); // 重新构建Request,确保后续能再次调用json() event.request = new Request(event.request, { body: bodyText, headers: event.request.headers }); } const response = await resolve(event); return response; }) satisfies Handle;
方案二:克隆请求后读取
先克隆原始Request对象,读取克隆后的请求体,这样原始请求的流不会被消耗,后续依然可以正常使用:
import type { Handle } from '@sveltejs/kit'; export const handle = (async ({ event, resolve }) => { if (['POST', 'PUT', 'PATCH'].includes(event.request.method)) { // 克隆原始请求,避免消耗原请求的流 const clonedRequest = event.request.clone(); const bodyText = await clonedRequest.text(); console.log('请求体内容:', bodyText); // 原始event.request仍可正常调用json()/text()等方法 } const response = await resolve(event); return response; }) satisfies Handle;
注意事项
- 不要盲目处理所有请求:GET/DELETE等请求通常没有请求体,无需处理。
- 若请求体是二进制数据,将
text()替换为arrayBuffer(),重新构建Request时传入对应的Buffer即可。
内容的提问来源于stack exchange,提问作者devzero
相关产品推荐
相关产品推荐

