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

cURL可正常访问REST API但Node.js中fetch请求失败排查

Udemy API fetch请求失败排查

cURL请求正常但node-fetch请求失败,核心是请求头不符合Udemy API的校验规则,加上代码本身存在几处疏漏,具体问题和修复方案如下:

存在的问题

  • 缺少必填的Accept请求头:cURL默认会携带Accept: */*头可以通过校验,但node-fetch默认的Accept头无法被Udemy API识别,会直接返回403/406错误。
  • 缺少合法的User-Agent头:Udemy API会拦截携带默认node-fetch标识的UA请求,cURL自带的UA在白名单内所以可以正常访问。
  • 未处理HTTP错误状态:node-fetch仅在网络连接失败时才会进入catch分支,4xx、5xx类的接口报错不会触发catch,直接调用res.json()会尝试解析错误页的HTML内容,直接抛出解析异常。
  • 凭证占位符未替换:当前代码里的client_id和client_secret是固定占位字符串,需要替换成你在Udemy开放平台申请的真实凭证,否则就算请求头正确也会返回401鉴权失败。
  • 服务启动逻辑缺失:当前代码没有调用app.listen()启动Express服务,写完路由逻辑后服务本身无法正常监听端口对外提供访问。
  • 接口调用位置不合理:当前fetch请求写在全局作用域,文件加载就会直接发起请求,没有和服务生命周期、路由逻辑绑定。

修复后的可运行代码

const fetch = require("node-fetch");
const express = require("express");
const app = express();
const port = process.env.PORT || 3000;
const path = require("path");

app.use(express.static("public"));
app.use(express.static(path.resolve(__dirname, "public")));
app.get("/", (req, res) => {
  res.sendFile("index.html", { root: __dirname });
});

app.get("/contact", (req, res) => {
  res.sendFile("contact.html", { root: __dirname });
});

// 替换为自己申请的真实凭证
const client_id = "你的真实client_id";
const client_secret = "你的真实client_secret";
const authToken = Buffer.from(`${client_id}:${client_secret}`).toString("base64");

async function getUdemyCourses() {
  try {
    const res = await fetch("https://www.udemy.com/api-2.0/courses/", {
      headers: {
        "Authorization": `Basic ${authToken}`,
        "Accept": "application/json, text/plain, */*",
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
      }
    })
    // 主动校验HTTP状态码
    if (!res.ok) {
      throw new Error(`请求失败,状态码:${res.status}, 错误信息:${await res.text()}`)
    }
    const data = await res.json()
    console.log("接口返回数据:", data)
    return data
  } catch (err) {
    console.error("请求Udemy接口出错:", err)
  }
}

// 服务启动成功后再发起接口请求
app.listen(port, () => {
  console.log(`服务运行在 http://localhost:${port}`)
  getUdemyCourses()
})

校验说明:以上代码补全的请求头和本地正常跑通的cURL请求头规则一致,不会被Udemy的拦截规则命中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 23:57:17