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

Next.js生产环境调用ERPNext DELETE API报500错误求助

Next.js生产环境向ERPNext发送DELETE请求返回500错误排查

问题描述

我有一个Next.js应用,需向ERPNext后端发送DELETE请求。本地环境运行完全正常——能发送请求并删除记录,但生产环境部署后,ERPNext返回500错误。用Postman发送相同请求可正常执行,因此推测问题出在Next.js应用的配置或代码中。

请求代码

export const deleteAPI = async (path) => {
  try {
    console.log("DELETE requested for path:", path);
    
    // 显式配置请求头,确保格式正确
    const url = `${BASE_URL}${path}`;
    const csrf = getCookies("csrf_token");
    
    // 构造请求头
    const headers = {
      "Accept": "application/json",
    };
    
    if (csrf) {
      headers["X-Frappe-CSRF-Token"] = csrf;
    }
    console.log("DELETE URL:", url);
    console.log("Headers:", JSON.stringify(headers));
    const response = await fetch(url, {
      method: "DELETE",
      headers: headers,
      credentials: "include"
    });
    
    console.log("Response status:", response.status);
    console.log("Response headers:", JSON.stringify(Object.fromEntries([...response.headers])));
    if (response.status === 204) {
      console.log("204 No Content响应 - 请求成功");
      return null;
    }
    const contentType = response.headers.get("content-type") || "";
    const text = await response.text();
    console.log("Response body:", text);
    
    let data = null;
    if (text) {
      if (contentType.includes("application/json")) {
        try {
          data = JSON.parse(text);
        } catch (e) {
          console.error("JSON解析失败:", e);
          data = { raw: text };
        }
      } else {
        data = { raw: text };
      }
    }
    
    if (!response.ok) {
      const err = new Error(
        (data && (data.message || data.error)) ||
          `HTTP ${response.status} ${response.statusText}`
      );
      err.status = response.status;
      err.response = data;
      throw err;
    }
    
    return data;
  } catch (error) {
    console.error("DELETE API错误:", error);
    handleFrappeApiError(error);
    throw error;
  }
};

生产环境日志

DELETE requested for path: /resource/Medical Department/test

Headers: {"Accept":"application/json","X-Frappe-CSRF-Token":"<token goes here>"}

DELETE URL: /api/erp/resource/Medical Department/test

Response headers: {"access-control-allow-credentials":"true","access-control-allow-headers":"Content-Type, X-Frappe-CSRF-Token, Authorization","access-control-allow-methods":"GET, POST, PUT, DELETE, OPTIONS","access-control-allow-origin":"<name of our origin is here","cf-cache-status":"DYNAMIC","cf-ray":"9763e14b4bd7ce62-SIN","content-type":"application/json","date":"Thu, 28 Aug 2025 12:40:57 GMT","nel":"{\"report_to\":\"cf-nel\",\"success_fraction\":0.0,\"max_age\":604800}","report-to":"{\"group\":\"cf-nel\",\"max_age\":604800,\"endpoints\":[{\"url\":\"<cloudflare url>\"}]}","server":"cloudflare","vary":"RSC, Next-Router-State-Tree, Next-Router-Prefetch, Origin"}

排查方向建议

  • URL编码问题:请求URL中的Medical Department包含空格,Postman会自动处理URL编码,但Next.js的fetch不会自动编码路径特殊字符。建议对路径分段编码:
    const encodedPath = path.split('/').map(segment => encodeURIComponent(segment)).join('/');
    const url = `${BASE_URL}${encodedPath}`;
    
  • CSRF Token有效性:检查生产环境中getCookies("csrf_token")获取的token是否与Postman请求中携带的一致,确认token未过期、跨域传递正常。
  • Cloudflare代理影响:生产环境通过Cloudflare代理,可能存在规则修改请求头或预处理请求的情况,检查Cloudflare是否对DELETE请求有额外限制。
  • ERPNext后端日志:500错误的具体原因需查看ERPNext服务器日志,对比Postman与生产环境请求的差异,定位后端触发错误的具体逻辑。
  • 请求体一致性:明确设置fetch的body: null,确保生产环境请求体与Postman一致,避免后端对空请求体的特殊处理逻辑触发错误。

内容的提问来源于stack exchange,提问作者Aizaz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 11:28:14