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

如何在Node.js中忽略或覆盖Content-Type请求头处理非JSON请求

问题

我有一个Node.js服务器,收到的请求Content-Type为application/json,但请求体并非JSON格式,而是如下形式的form-urlencoded原始文本:

client_id=q9r71WPJtK5JWbkq7LAATEhQoXHQCJ9z&code_verifier=CiC6e0mZirQAwKkLvhiitiVuEvf2ZaFD7hsENkAhxyO&grant_type=authorization_code&code=TkdVtUfvtb4vKyJTRa9Z5F5G6_R8cwj6eIR6VGd0Tt0XX&redirect_uri=https%3A%2F%2Fuat.test.com.au

在Postman中测试时,若设置Content-Type为application/json,服务器接收的req.body为空对象{};若设置为text/plain,则能正确获取请求体。由于正在模拟外部供应商系统,短期内无法修改其请求的Content-Type。请问是否有办法强制Node.js将该请求视为文本而非JSON来处理?

当前使用的Express代码如下:

const express = require('express');
const app = express();
const PORT = 3000;
 
// Without this middleware
app.use(express.text());
app.post('/oauth/token', function (req, res) {
    console.log(req.body);
    res.end();
})
 
app.listen(PORT, function (err) {
    if (err) console.log(err);
    console.log("Server listening on PORT", PORT);
});

Postman生成的curl示例如下:

curl --location 'http://127.0.0.1:3000/oauth/token' \
--header 'content-type: application/json' \
--data 'client_id=q9r71WPJtK5JWbkq7LAATEhQoXHQCJ9z&code_verifier=CiC6e0mZirQAwKkLvhiitiVuEvf2ZaFD7hsENkAhxyO&grant_type=authorization_code&code=TkdVtUfvtb4vKyJTRa9Z5F5G6_R8cwj6eIR6VGd0Tt0XX&redirect_uri=https%3A%2F%2Fuat.tab.com.au'

目前尝试的方向是寻找忽略或覆盖请求头中Content-Type的方法。

解决方案

方法1:扩展express.text()的类型匹配规则

express.text()默认仅处理text/plain类型请求,可通过type参数扩展匹配范围,让它同时处理application/json类型请求:

const express = require('express');
const app = express();
const PORT = 3000;

// 让text中间件兼容application/json和text/plain类型
app.use(express.text({ type: ['text/plain', 'application/json'] }));

app.post('/oauth/token', function (req, res) {
    console.log('原始请求体:', req.body);
    // 若需要解析为对象,可使用querystring模块处理
    const querystring = require('querystring');
    const parsedBody = querystring.parse(req.body);
    console.log('解析后的对象:', parsedBody);
    res.end();
})

app.listen(PORT, function (err) {
    if (err) console.log(err);
    console.log("Server listening on PORT", PORT);
});

方法2:自定义中间件强制读取请求体为文本

如果需要更灵活的控制,可编写自定义中间件,直接读取请求流并转换为文本,完全忽略请求头的Content-Type:

const express = require('express');
const app = express();
const PORT = 3000;

// 自定义中间件:强制读取请求体为文本
app.use((req, res, next) => {
    let rawData = '';
    req.on('data', chunk => {
        rawData += chunk.toString();
    });
    req.on('end', () => {
        req.body = rawData;
        next();
    });
});

app.post('/oauth/token', function (req, res) {
    console.log('原始请求体:', req.body);
    // 可选:解析为form-urlencoded对象
    const querystring = require('querystring');
    const parsedBody = querystring.parse(req.body);
    console.log('解析后的对象:', parsedBody);
    res.end();
})

app.listen(PORT, function (err) {
    if (err) console.log(err);
    console.log("Server listening on PORT", PORT);
});

方法3:用express.urlencoded直接解析为对象

由于请求体本身是form-urlencoded格式,可让express.urlencoded处理application/json类型请求,直接得到解析后的对象:

const express = require('express');
const app = express();
const PORT = 3000;

// 让urlencoded中间件兼容application/json和标准form-urlencoded类型
app.use(express.urlencoded({ 
    extended: true,
    type: ['application/x-www-form-urlencoded', 'application/json']
}));

app.post('/oauth/token', function (req, res) {
    // 直接获取解析后的对象
    console.log(req.body);
    res.end();
})

app.listen(PORT, function (err) {
    if (err) console.log(err);
    console.log("Server listening on PORT", PORT);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 15:31:15