部署Vercel后Flask接口仅Fetch请求返回400 Bad Request问题
问题描述
我最近为网站实现了一套报告系统,本地运行正常,但部署到Vercel后,使用Fetch请求Flask后端的/vulnerability/get接口时会返回“Bad Request”错误,我确认代码逻辑没有问题。
Flask后端代码
@app.route("/vulnerability/get",methods=["POST"]) def report_get(): return get_report(request.json.get("id"))
触发问题的SvelteKit前端代码(路径/report/manage/[slug]/+page.ts)
import { serverURL } from '../../../../serverContactor'; export async function load({ params,fetch }){ let code=params.slug; let body = {"id":code as string}; const dataRequest = await fetch(`${serverURL}/vulnerability/get`,{ method:"POST", headers:{"Content-Type":"application/json"}, body: JSON.stringify(body) }); let data; try { data = await dataRequest.json(); } catch(error) { return {"Error":true,"name":error as string,"response":dataRequest, "code":code as string} } return data; }
应用错误日志
{ Error: true, name: SyntaxError: Unexpected token '<', "<!doctype "... is not valid JSON at JSON.parse (<anonymous>) at Proxy.<anonymous> (file:///var/task/.svelte-kit/output/server/index.js:693:25) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async load (file:///var/task/.svelte-kit/output/server/entries/pages/report/manage/_slug_/_page.ts.js:14:12) at async load_data (file:///var/task/.svelte-kit/output/server/index.js:600:18) at async file:///var/task/.svelte-kit/output/server/index.js:2085:18, response: Response { status: 400, statusText: 'Bad Request', headers: Headers { 'access-control-allow-credentials': 'true', 'access-control-allow-headers': 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version', 'access-control-allow-methods': 'GET,OPTIONS,PATCH,DELETE,POST,PUT', 'access-control-allow-origin': 'https://frii-site-frontend-ezejbxuv9-ctih1s-projects.vercel.app', 'cache-control': 'public, max-age=0, must-revalidate', connection: 'keep-alive', 'content-length': '167', 'content-type': 'text/html; charset=utf-8', date: 'Wed, 10 Jul 2024 07:06:09 GMT', server: 'Vercel', 'strict-transport-security': 'max-age=63072000', vary: 'Origin', 'x-vercel-cache': 'MISS', 'x-vercel-id': 'arn1:sfo1:sfo1:iad1::iad1::kf868-1720595169898-50deaf4d69a8' }, body: ReadableStream { locked: true, state: 'closed', supportsBYOB: true }, bodyUsed: true, ok: false, redirected: false, type: 'basic', url: 'https://server.frii.site/vulnerability/get' }, code: 'WYC6EG9oYpNClQYtUdBSFovH' }
正常工作的对比情况
- 使用Insomnia调用该接口完全正常,仅Fetch请求出现问题。
- 前端本地运行时应用正常,后端部署位置不影响功能。
- 另一个页面
/report/track/+page.ts中使用相同接口也能正常工作,代码如下:
import { serverURL } from '../../../serverContactor'; export async function load({ url,fetch }) { let code:string|null=url.searchParams.get("code"); let body = { "id":code }; const dataRequest = await fetch(`${serverURL}/vulnerability/get`,{ method:"POST", headers:{"Content-Type":"application/json"}, body: JSON.stringify(body) }); const data = await dataRequest.json(); return data; }
- 以下代码在
playcode.io中也能正常运行:
async function load(params:string,serverURL:string) { let code=params; let body = {"id":code as string}; const dataRequest = await fetch(`${serverURL}/vulnerability/get`,{ method:"POST", headers:{"Content-Type":"application/json"}, body: JSON.stringify(body) }); let data; dataRequest.text().then(text=>{ console.log(`Headers: ${dataRequest.headers} body: ${dataRequest.body} body used: ${dataRequest.bodyUsed} text: ${text} code:${code}`); }); return data; }
附:前端使用SvelteKit框架。
问题排查与解决方案
从错误日志看,后端返回的是HTML而非JSON,说明请求没有被正确路由到Flask接口,可按以下方向排查:
检查Vercel路由配置
确认vercel.json中的路径重写/代理规则,确保/vulnerability/get的请求被正确转发到Flask后端,而非被Vercel当作前端路由或静态资源处理。修正SvelteKit服务器端Fetch的差异
SvelteKitload函数中的fetch是服务器端实例,和客户端Fetch存在差异:- 显式添加
credentials: 'include'配置(如果后端需要身份验证) - 检查
serverURL的环境变量配置,确保服务器端和客户端使用相同的地址
- 显式添加
验证请求内容的一致性
在报错的load函数中添加日志,确认body的JSON字符串没有异常字符;对比正常请求(Insomnia、其他页面)的请求头和Body,排查是否存在隐性差异。Flask后端添加调试日志
在Flask接口中打印请求头和原始数据,确认请求是否正确到达后端,以及JSON解析是否失败:@app.route("/vulnerability/get",methods=["POST"]) def report_get(): print("Request Headers:", request.headers) print("Request Body:", request.get_data()) return get_report(request.json.get("id"))
内容的提问来源于stack exchange,提问作者SuperSIlly2
相关产品推荐
相关产品推荐

