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

使用Fetch API发送POST请求本地返回401但Postman可正常请求

问题分析与解决方案

核心问题:mode: 'no-cors'导致认证头失效

你代码里设置的mode: 'no-cors'是关键问题——在这个模式下,浏览器会强制限制请求头的发送,自定义的Authorization和Content-Type: application/json头会被忽略或替换为简单头,服务器根本收不到正确的Basic认证信息,自然返回401。另外,no-cors模式下你无法读取真实的响应内容,调试也会受阻。

Postman不受浏览器CORS政策限制,所以能正常发送所有请求头;而Postman Mock服务器本身已经配置了兼容CORS的响应头,所以本地请求能成功。

分步解决方案

1. 移除mode: 'no-cors'

首先修改fetch配置,删掉这一行,让浏览器以正常模式发送请求:

fetch("你的目标URL", {
    // 删掉 mode: 'no-cors'
    method: "POST",
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Basic ' + btoa(encodeURIComponent(username) + ":" + encodeURIComponent(password))
    }, 
    body: JSON.stringify(data)
})

注:用encodeURIComponent处理用户名/密码,避免包含特殊字符时btoa编码失败

2. 处理CORS跨域问题

移除no-cors后,浏览器会触发CORS预检请求(OPTIONS),需要确保目标服务器配置了正确的CORS响应头:

  • 如果服务器由你控制,添加以下响应头:

    • Access-Control-Allow-Origin: http://127.0.0.1:5500(Live Server默认地址,或者用*允许所有来源,生产环境不推荐)
    • Access-Control-Allow-Headers: Content-Type, Authorization(允许自定义头)
    • Access-Control-Allow-Methods: POST, OPTIONS(允许POST和预检OPTIONS请求)

    比如用Express框架时,可以用cors中间件快速配置:

    const cors = require('cors');
    app.use(cors({
      origin: 'http://127.0.0.1:5500',
      allowedHeaders: ['Content-Type', 'Authorization'],
      methods: ['POST', 'OPTIONS']
    }));
    
  • 如果服务器不由你控制,使用本地代理绕过跨域限制:
    写一个简单的Node.js代理服务器,将本地请求转发到目标服务器:

    const http = require('http');
    const https = require('https');
    const { URL } = require('url');
    
    const proxyServer = http.createServer((req, res) => {
      const targetUrl = new URL("你的目标服务器URL");
      const options = {
        hostname: targetUrl.hostname,
        port: targetUrl.port || (targetUrl.protocol === 'https:' ? 443 : 80),
        path: targetUrl.pathname + req.url,
        method: req.method,
        headers: { ...req.headers, host: targetUrl.hostname }
      };
    
      const proxyReq = (targetUrl.protocol === 'https:' ? https : http).request(options, proxyRes => {
        res.writeHead(proxyRes.statusCode, proxyRes.headers);
        proxyRes.pipe(res, { end: true });
      });
    
      req.pipe(proxyReq, { end: true });
    });
    
    proxyServer.listen(3000, () => console.log('代理服务器运行在http://localhost:3000'));
    

    启动代理后,把fetch的URL改成http://localhost:3000即可。

3. 完善请求错误处理

添加错误捕获逻辑,方便调试请求失败的原因:

fetch(...)
.then(res => {
    if (!res.ok) {
        throw new Error(`请求失败:${res.status} ${res.statusText}`);
    }
    return res.json(); // 若服务器返回JSON数据
})
.then(data => console.log("请求成功:", data))
.catch(err => console.error("请求出错:", err));

修正后的完整代码

<!DOCTYPE html>
<html>
<head>
  <title>Title</title>
</head>
<body>
    <input id="name" type="text" name="name" placeholder="name">
    <input type="text" id="username" name="username">
    <input type="password" id="password" name="password">
    <button type="submit" onclick="JSONTest()"> Submit </button>

  <script type="text/javascript">
    const JSONTest = function() {
        const name = document.getElementById("name").value;
        const username = document.getElementById("username").value;
        const password = document.getElementById("password").value;
        
        const data = {title: name};

        fetch("你的目标URL", {
            method: "POST",
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Basic ' + btoa(encodeURIComponent(username) + ":" + encodeURIComponent(password))
            }, 
            body: JSON.stringify(data)
        })
        .then(res => {
            if (!res.ok) throw new Error(`请求失败:${res.status}`);
            return res.json();
        })
        .then(data => console.log("请求成功!响应:", data))
        .catch(err => console.error("请求出错:", err));
    };
  </script>
</body>
</html>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 10:15:12