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

为何jQuery post()方法发送的是GET请求而非POST请求?

问题描述

我有一个简单的单文件应用,用于演示如何与API服务器进行摘要认证交互。第一步本应是不带凭证发送POST请求以获取nonce,但调用$.post(...)时,网络追踪显示发送的是GET请求,控制台记录“method not allowed”。

控制台显示状态码405,但代码中获取到的request.status是404。我真正关注的是本该发送POST请求并得到401响应。

我查找了许多关于jQuery发送POST而非GET的问题,但大多较旧,解决方案对我无效或不适用。我确认使用的是jQuery 3.5.1,因此关于type与method的旧答案不适用。

在Chrome和Edge中均出现此问题。将下方代码保存为index.html并在Chrome中打开,点击按钮会发送GET请求。请求google.com可能成功,但为何是GET?若换成我的REST API服务器地址,会因该端点不支持GET而返回405。

我怀疑忽略了某些明显问题,但不知具体是什么。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>SSO Test Client</title>
    <link rel="stylesheet" href="lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="css/site.css" />
    <script src="lib/jquery/dist/jquery.min.js"></script>
    <script src="lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="js/site.js" asp-append-version="true"></script>
    <style>
      input[type="text"] {
          width: 50em;
      }
    </style>
</head>
<body>
    <script>
        async function init() {
            console.log(jQuery().jquery);

            // Doesn't matter what I put here, it fails
            $("#server").val("https://google.com");

            $("#submit").click(handleSubmit);
        };

        function handleSubmit() {
            var server = $("#server").val();
            // Get nonce from API server by attempting to post without credentials
            // and handling the challenge response.
            $.post({
                url: server,
                dataType: "jsonp",  // I get back a 0 response without this
                headers: {
                    'Content-Type':'application/json'  //  The server seems to require this
                },
                data: {},
                success: function (data, textStatus, request) {
                    // This should never succeed; we expect a 401
                    alert(textStatus);
                },
                // Adapted from https://stackoverflow.com/a/14563181/7685
                error: function (request, textStatus, errorThrown) {
                    var msg = "";

                    if (request.status == 0) {
                        msg = `Could not connect to "${server}".`;
                    }
                    else if (request.status == 404) {
                        msg = "Page not found (404)";
                    }
                    else if (request.status == 405) {
                        msg = "Method not allowed (405)";
                    }
                    else if (request.status == 500) {
                        msg = "Internal server error (500)";
                    }
                    // This is expected.
                    else if (request.status == 401) {
                        msg = "Got nonce from server.";
                    }
                    else {
                        msg = "Unhandled status. " + textStatus;
                    }

                    alert(msg);
                }
            });
        };

        function docReady(fn) {
            // see if DOM is already available
            if (document.readyState === "complete" || document.readyState === "interactive") {
                // call on next available tick
                setTimeout(fn, 1);
            } else {
                document.addEventListener("DOMContentLoaded", fn);
            }
        };

        docReady(init);
    </script>
    <div class="container">
        <main role="main" class="pb-3">
            <div class="text-center">
                <div id="sso-client">
                    <input id="server" type="text"
                           title="API server to use for SSO authorization" />
                    <br />
                    <input type="button" id="submit" value="Test"
                           title="Try to get a nonce" onclick=""/>
                </div>
            </div>
        </main>
    </div>
</body>
</html>

补充说明:

  • 我认为是jsonp数据类型导致jQuery将POST转为GET,但去掉jsonp后,请求无法发出,状态码为0。若移除jsonp,我需要知道如何让请求正常发送。
  • 我尝试在$.post()前添加jQuery.support.cors = true;,但无效果。
  • 我认为无需修改服务器(如设置Access-Control-Allow-Origin),因为同一台电脑上用Postman可正常操作,无需特殊源处理。
解决方案

1. 核心问题:JSONP强制转为GET请求

JSONP的工作原理是通过创建<script>标签加载远程资源,而<script>标签只能发起GET请求,所以只要设置了dataType: "jsonp",不管用$.post还是$.ajax指定method: "POST",最终都会被转为GET请求,这是JSONP的固有特性,和jQuery版本无关。这就是POST变GET的根本原因。

2. 解决跨域问题,移除JSONP

去掉dataType: "jsonp"后出现的状态码0,是浏览器的CORS(跨域资源共享)限制导致的。Postman不受浏览器同源策略限制,所以能正常请求,但浏览器中运行的前端代码必须遵守同源规则。

解决这个问题有两种可行方案:

  • 方案一:配置服务器支持CORS
    这是标准跨域解决方案,需要在API服务器上添加CORS响应头,比如:

    Access-Control-Allow-Origin: * (或指定你的前端页面域名)
    Access-Control-Allow-Methods: POST, GET, OPTIONS
    Access-Control-Allow-Headers: Content-Type
    

    由于请求携带了自定义的Content-Type: application/json,属于预检请求(OPTIONS)范畴,服务器需要正确响应OPTIONS请求,否则浏览器会拦截后续的POST请求。

  • 方案二:使用代理服务器
    如果无法修改API服务器,可以在前端部署代理服务器,让前端请求先发送到同源的代理服务器,再由代理服务器转发到目标API服务器。比如本地开发时,可用Nginx或Node.js搭建简单代理。

3. 修正后的请求代码示例

移除dataType: "jsonp",确保服务器已配置CORS后,修改后的handleSubmit函数如下:

function handleSubmit() {
    var server = $("#server").val();
    $.ajax({
        url: server,
        method: "POST",
        headers: {
            'Content-Type':'application/json'
        },
        data: JSON.stringify({}), // 发送JSON格式数据需要序列化
        success: function (data, textStatus, request) {
            alert(textStatus);
        },
        error: function (request, textStatus, errorThrown) {
            var msg = "";

            if (request.status == 0) {
                msg = `Could not connect to "${server}".`;
            }
            else if (request.status == 404) {
                msg = "Page not found (404)";
            }
            else if (request.status == 405) {
                msg = "Method not allowed (405)";
            }
            else if (request.status == 500) {
                msg = "Internal server error (500)";
            }
            else if (request.status == 401) {
                msg = "Got nonce from server.";
            }
            else {
                msg = "Unhandled status. " + textStatus;
            }

            alert(msg);
        }
    });
};

注意:改用$.ajax并明确指定method: "POST"(显式指定更清晰),同时将data用JSON.stringify序列化,因为Content-Type设置为application/json时,需要发送JSON字符串而非对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 12:01:00