You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

部署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接口,可按以下方向排查:

  1. 检查Vercel路由配置
    确认vercel.json中的路径重写/代理规则,确保/vulnerability/get的请求被正确转发到Flask后端,而非被Vercel当作前端路由或静态资源处理。

  2. 修正SvelteKit服务器端Fetch的差异
    SvelteKitload函数中的fetch是服务器端实例,和客户端Fetch存在差异:

    • 显式添加credentials: 'include'配置(如果后端需要身份验证)
    • 检查serverURL的环境变量配置,确保服务器端和客户端使用相同的地址
  3. 验证请求内容的一致性
    在报错的load函数中添加日志,确认body的JSON字符串没有异常字符;对比正常请求(Insomnia、其他页面)的请求头和Body,排查是否存在隐性差异。

  4. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 04:14:52