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

node-fetch返回空响应,为何与REST客户端表现不一致?

问题描述

使用node-fetch 2.6.6请求OAUTH2 Access Token(JWT)时返回空响应{"size": 0, "timeout": 0},但用REST客户端以表单编码提交相同参数能成功获取令牌。

我的代码

async function getAccessToken() {
    if (argumentParserResult.authenticationScheme == 'OAUTH2') {
        const fetch = require('node-fetch');
        const url = argumentParserResult.resourceUrl;
        let body = {
            'grant_type': 'client_credentials',
            'client_id': argumentParserResult.clientId,
            'scope': argumentParserResult.clientScope,
            'client_secret': argumentParserResult.clientSecret
        }
        console.log('POST ' + argumentParserResult.authorizationUrl);
        console.log(JSON.stringify(body));
        let response = await fetch(argumentParserResult.authorizationUrl, {
            method: 'POST',
            body: JSON.stringify(body)
        });
        console.log('Access token request repsonse: ' + JSON.stringify(response));
        process.exit(1);
    }
}

REST客户端请求详情

POST指定URL,表单编码参数:

grant_type: client_credentials
client_id: some-client-id
scope: some-long-scope-string
client_secret: client-secret

问题原因及修复

你的代码存在两个核心问题:

  1. 请求体格式不匹配:OAUTH2的client_credentials模式要求请求体使用application/x-www-form-urlencoded(表单编码)格式,但你用JSON.stringify(body)发送了JSON格式的请求体,服务端无法识别解析,因此返回空响应。
  2. 未正确获取响应内容:直接对fetch返回的Response对象执行JSON.stringify()是错误的,该对象是响应元数据容器,不是实际的响应体内容,需要调用专属方法解析。

修正后的代码

async function getAccessToken() {
    if (argumentParserResult.authenticationScheme == 'OAUTH2') {
        const fetch = require('node-fetch');
        // 用URLSearchParams构造表单编码的请求体,符合OAUTH2要求
        const body = new URLSearchParams({
            'grant_type': 'client_credentials',
            'client_id': argumentParserResult.clientId,
            'scope': argumentParserResult.clientScope,
            'client_secret': argumentParserResult.clientSecret
        });
        console.log('POST ' + argumentParserResult.authorizationUrl);
        console.log(body.toString());
        const response = await fetch(argumentParserResult.authorizationUrl, {
            method: 'POST',
            body: body,
            headers: {
                // 显式设置Content-Type,node-fetch 2.x会自动识别URLSearchParams并设置,但显式声明更稳妥
                'Content-Type': 'application/x-www-form-urlencoded'
            }
        });
        // 解析响应体的实际内容
        const tokenData = await response.json();
        console.log('Access token response data: ', tokenData);
        process.exit(1);
    }
}

额外说明

  • node-fetch 2.x中,当请求体为URLSearchParams类型时,会自动设置Content-Type请求头,但显式声明可以避免潜在的兼容问题。
  • 如果服务端返回非JSON格式的响应,可以改用response.text()来获取内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 01:00:59