CORS - jQuery 获取 ajax 响应状态失败

Posted

技术标签:

【中文标题】CORS - jQuery 获取 ajax 响应状态失败【英文标题】:CORS - jQuery get ajax response status failing 【发布时间】:2018-10-15 20:26:33 【问题描述】:

我遇到了对不同子域的 ajax 调用问题,请求从 www.mydomain.test 发送到 subdomain1.mydomain.test。我想处理 4xx 和 5xx 错误,以便重定向用户。

当从 FF 或 Chromium 执行时,当服务器返回 200 时调用完美运行,没有报告 CORS 问题,但是当服务器返回 4xx 时,jqXHR.status 属性设置为 0 并且我在控制台上收到以下 CORS 消息:

Failed to load http://subdomain1.mydomain.test/api.php: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://www.mydomain.test' is therefore not allowed access. The response had HTTP status code 418.

但是,使用 Postman 执行相同的调用总是会成功,即使服务器返回 418 或任何其他 4xx。

这是 JS 代码,从 www.mydomain.test 执行:

$.ajax(
    url : "http://subdomain1.mydomain.test/api.php",
    type : "POST",
    success: function(response)
    
        redirectToSucessPage();
    ,
    error: function(jqXHR, textStatus, errorThrown)
    
        console.log(textStatus); //prints out "error"
        console.log(jqXHR.status); //prints out 0

        if(jqXHR.status == 401) //never reached
            redirectToErrorPage();
    
);

这是完整的控制台输出:

POST http://subdomain1.mydomain.test/api.php 418 ()
Failed to load http://subdomain1.mydomain.test/api.php: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://www.mydomain.test' is therefore not allowed access. The response had HTTP status code 418.
error
0

CORS 消息并没有完全困扰我,虽然我很困惑,因为它只发生在 4xx 响应中,但我真的需要响应的状态代码。服务器返回 418,但 jqXHR.status 为 0。

这是资源的 nginx 配置:

location = /api.php                    
    root /path/to/dir;

    add_header 'Access-Control-Allow-Origin' 'http://www.mydomain.test';
    add_header 'Access-Control-Allow-Methods' 'POST';

    limit_req   zone=limitZoneOne   burst=5;

    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php7.0-fpm.sock;

产生响应的 PHP 很简单:

http_response_code(418) and exit;

我在获取响应状态时是否犯了错误,或者是否存在一些我不知道的 4xx 响应的 CORS 问题?谢谢!

【问题讨论】:

还需要允许 OPTIONS 方法并在发送 POST 之前处理必须包含访问控制标头的预检 OPTIONS 请求。阅读 CORS 的工作原理 我之前曾尝试在 nginx 上允许 OPTIONS,但没有任何区别。对于问题可能是什么,或者代码/配置中缺少什么,您有什么具体建议吗? 您只需要在add_header 语句中指定always 参数即可。否则,只有在响应码为 200、201、204、206、301、302、303、304、307 或 308 时,nginx 才会添加 header。但如果指定 always 参数,则会添加 header 字段无论响应代码如何。见nginx.org/en/docs/http/ngx_http_headers_module.html#add_header @sideshowbarker 感谢您的提示,我刚刚尝试将 always 与 add_header 一起使用,但结果是一样的。不过,more_set_headers 就像一个魅力。 【参考方案1】:

通过在 nginx.conf 上使用 more_set_headers 而不是 add_header 解决:

location = /api.php                    
    root /path/to/dir;

    more_set_headers 'Access-Control-Allow-Origin:http://www.mydomain.test';
    more_set_headers 'Access-Control-Allow-Methods: POST';

    limit_req   zone=limitZoneOne   burst=5;

    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php7.0-fpm.sock;

即使没有 Access-Control-Allow-Methods 标头也可以在 FF 和 Chromium 上工作。

more_set_headers 指令是 HttpHeadersMore 模块的一部分,该模块包含在 nginx 的 nginx-extras flavor 中,您可以通过以下操作将其安装在 ubuntu 16 上:

sudo apt-get install nginx-extras

【讨论】:

以上是关于CORS - jQuery 获取 ajax 响应状态失败的主要内容,如果未能解决你的问题,请参考以下文章

jQuery ajax 和 CORS 不起作用

jQuery ajax 和 CORS 不起作用

在 PhoneGap+jQuery Mobile 中使用 ajax 的 CORS 无法在设备上运行,但在浏览器上运行

Django jquery ajax cors错误

jQuery ajax CORS 请求

jQuery 和 CORS