React发送的POST请求在Node.js服务器中变为GET的问题排查
在React客户端发送的POST请求,到达Node.js服务器时被转为GET请求。
React客户端代码
function SavePatient(event) { event.preventDefault(); console.log("Saving Patient Data"); console.log(patientData); fetch('http://localhost:3001', { Method: 'POST', Headers: { 'Accept': 'application/json', 'Content-Type': 'multipart/form-data' }, Body: JSON.stringify(patientData), Cache: 'default' }); }
Node.js服务器代码
function requestListener(req,res) { res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader( 'Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); console.log(req.url,req.method,req.headers); const url = req.url; const body = []; let parsedBody = ""; function readData(chunk) { console.log(chunk); body.push(chunk); } function endReadData(chunk) { parsedBody = Buffer.concat(body).toString(); console.log(parsedBody); } if (url === '/savepatient') { const body = []; req.on('data', readData); req.on('end', endReadData); res.setHeader('Content-Type', 'text/json'); res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader( 'Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); res.write('{"name":"John", "age":30, "car":null}'); console.log('Saving...'); fs.writeFileSync('storage/message.txt','TESTE'); return res.end(); } }
服务器收到的请求信息
/ GET {
host: 'localhost:3001',
connection: 'keep-alive',
'sec-ch-ua': '"Chromium";v="112", "Google Chrome";v="112", "Not:A-Brand";v="99"',
'sec-ch-ua-mobile': '?0',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36',
'sec-ch-ua-platform': '"Windows"',
accept: '/',
origin: 'http://localhost:3000',
'sec-fetch-site': 'same-site',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
referer: 'http://localhost:3000/',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en,en-US;q=0.9,es;q=0.8,pt-BR;q=0.7,pt;q=0.6'
}
Postman测试POST请求正常,但React客户端发送时服务器收到GET请求,期望POST请求正常到达服务器。
1. 修正Fetch配置的属性名
Fetch API的初始化对象属性名必须是小写(method、headers、body),你代码里用了首字母大写的Method、Headers、Body,这些属性会被Fetch忽略,导致默认发送GET请求。
2. 修正请求URL
服务器处理POST请求的端点是/savepatient,但你当前请求的是根路径http://localhost:3001,需要把URL改为http://localhost:3001/savepatient。
3. 修正Content-Type与请求体的匹配
你用JSON.stringify(patientData)生成JSON格式的请求体,但设置了Content-Type: multipart/form-data,两者不匹配:
- 如果发送JSON数据,应将Content-Type改为
application/json; - 如果确实需要发送
multipart/form-data,要构建FormData对象作为body,而非JSON字符串。
修复后的React代码
function SavePatient(event) { event.preventDefault(); console.log("Saving Patient Data"); console.log(patientData); fetch('http://localhost:3001/savepatient', { method: 'POST', // 小写 headers: { // 小写 'Accept': 'application/json', 'Content-Type': 'application/json' // 匹配JSON请求体 }, body: JSON.stringify(patientData), // 小写 cache: 'default' // 小写 }) .then(response => response.json()) .catch(error => console.error('请求错误:', error)); // 建议添加错误捕获 }
额外优化(服务器端)
服务器当前在/savepatient分支里重复设置CORS头,可统一配置;同时要处理浏览器跨域请求前的OPTIONS预检请求:
function requestListener(req,res) { // 统一设置CORS头 res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS'); // 处理OPTIONS预检请求 if (req.method === 'OPTIONS') { res.writeHead(200); return res.end(); } console.log(req.url, req.method, req.headers); const url = req.url; const body = []; let parsedBody = ""; function readData(chunk) { console.log(chunk); body.push(chunk); } function endReadData() { parsedBody = Buffer.concat(body).toString(); console.log(parsedBody); // 读取完请求体后再返回响应 res.setHeader('Content-Type', 'application/json'); res.write('{"name":"John", "age":30, "car":null}'); console.log('Saving...'); fs.writeFileSync('storage/message.txt','TESTE'); return res.end(); } if (url === '/savepatient' && req.method === 'POST') { req.on('data', readData); req.on('end', endReadData); } else { // 处理其他请求或返回404 res.writeHead(404); res.end('Not Found'); } }
内容的提问来源于stack exchange,提问作者Fabian Cerqueira

