jQuery $.ajax(), $.post 在 Firefox 中发送“OPTIONS”作为 REQUEST_METHOD

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1099787/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 10:40:30  来源:igfitidea点击:

jQuery $.ajax(), $.post sending "OPTIONS" as REQUEST_METHOD in Firefox

ajaxfirefoxjquery-pluginsjquery

提问by fitzgeraldsteele

Having trouble with what I thought was a relatively simple jQuery plugin...

遇到了我认为是一个相对简单的 jQuery 插件的问题...

The plugin should fetch data from a php script via ajax to add options to a <select>. The ajax request is pretty generic:

该插件应通过 ajax 从 php 脚本中获取数据,以将选项添加到<select>. ajax 请求非常通用:

$.ajax({
  url: o.url,
  type: 'post',
  contentType: "application/x-www-form-urlencoded",
  data: '{"method":"getStates", "program":"EXPLORE"}',
  success: function (data, status) {
    console.log("Success!!");
    console.log(data);
    console.log(status);
  },
  error: function (xhr, desc, err) {
    console.log(xhr);
    console.log("Desc: " + desc + "\nErr:" + err);
  }
});

This seems to work fine in Safari. In Firefox 3.5, the REQUEST_TYPEon the server is always 'OPTIONS', and the $_POST data does not appear. Apache logs the request as type 'OPTIONS':

这在 Safari 中似乎运行良好。在 Firefox 3.5 中,REQUEST_TYPE服务器上的 始终是 'OPTIONS',并且 $_POST 数据不会出现。Apache 将请求记录为“OPTIONS”类型:

::1 - - [08/Jul/2009:11:43:27 -0500] "OPTIONS sitecodes.php HTTP/1.1" 200 46

Why would this ajax call work in Safari, but not Firefox, and how do I fix it for Firefox?

为什么这个 ajax 调用可以在 Safari 中工作,而不能在 Firefox 中工作,我该如何为 Firefox 修复它?

Response Headers
Date: Wed, 08 Jul 2009 21:22:17 GMT
Server:Apache/2.0.59 (Unix) PHP/5.2.6 DAV/2
X-Powered-By: PHP/5.2.6
Content-Length  46
Keep-Alive  timeout=15, max=100
Connection  Keep-Alive
Content-Type    text/html

Request Headers
Host    orderform:8888
User-Agent  Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1) Gecko/20090624 Firefox/3.5
Accept  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip,deflate
Accept-Charset  ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive  300
Connection  keep-alive
Origin  http://ux.inetu.act.org
Access-Control-Request-Method   POST
Access-Control-Request-Headers  x-requested-with

Here is a picture of the Firebug output:

这是 Firebug 输出的图片:

采纳答案by Jonas Skovmand

The reason for the error is the same origin policy. It only allows you to do XMLHTTPRequests to your own domain. See if you can use a JSONPcallback instead:

错误的原因是同源策略。它只允许您对自己的域执行 XMLHTTPRequests。看看是否可以改用JSONP回调:

$.getJSON( 'http://<url>/api.php?callback=?', function ( data ) { alert ( data ); } );

回答by Juha Palom?ki

I used the following code on Django side to interpret the OPTIONS request and to set the required Access-Control headers. After this my cross domain requests from Firefox started working. As said before, the browser first sends the OPTIONS request and then immediately after that the POST/GET

我在 Django 端使用以下代码来解释 OPTIONS 请求并设置所需的 Access-Control 标头。在此之后,我来自 Firefox 的跨域请求开始工作。如前所述,浏览器首先发送 OPTIONS 请求,然后立即发送 POST/GET

def send_data(request):
    if request.method == "OPTIONS": 
        response = HttpResponse()
        response['Access-Control-Allow-Origin'] = '*'
        response['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
        response['Access-Control-Max-Age'] = 1000
        # note that '*' is not valid for Access-Control-Allow-Headers
        response['Access-Control-Allow-Headers'] = 'origin, x-csrftoken, content-type, accept'
        return response
    if request.method == "POST":
        # ... 

Edit: it seems to be that at least in some cases you also need to add the same Access-Control headers to the actual response. This can be a little bit confusing, since the request seems to succeed, but Firefox does not pass the contents of the response to the Javascript.

编辑:似乎至少在某些情况下,您还需要将相同的 Access-Control 标头添加到实际响应中。这可能有点令人困惑,因为请求似乎成功了,但 Firefox 不会将响应的内容传递给 Javascript。

回答by Mike C

This mozilla developer center articledescribes various cross-domain request scenarios. The article seems to indicate that a POST request with content type of 'application/x-www-form-urlencoded' should be sent as a 'simple request' (with no 'preflight' OPTIONS request). I found , however, that Firefox sent the OPTIONS request, even though my POST was sent with that content type.

这篇 mozilla 开发者中心文章描述了各种跨域请求场景。这篇文章似乎表明内容类型为“application/x-www-form-urlencoded”的 POST 请求应该作为“简单请求”发送(没有“预检”选项请求)。然而,我发现 Firefox 发送了 OPTIONS 请求,即使我的 POST 是使用该内容类型发送的。

I was able to make this work by creating an options request handler on the server, that set the 'Access-Control-Allow-Origin' response header to '*'. You can be more restrictive by setting it to something specific, like 'http://someurl.com'. Also, I have read that, supposedly, you can specify a comma-separated list of multiple origins, but I couldn't get this to work.

我能够通过在服务器上创建一个选项请求处理程序来完成这项工作,该处理程序将“Access-Control-Allow-Origin”响应标头设置为“*”。您可以通过将其设置为特定的内容来限制更多,例如“ http://someurl.com”。另外,我已经读过,据说您可以指定一个逗号分隔的多个来源列表,但我无法使其正常工作。

Once Firefox receives the response to the OPTIONS request with an acceptable 'Access-Control-Allow-Origin' value, it sends the POST request.

一旦 Firefox 收到具有可接受的“Access-Control-Allow-Origin”值的 OPTIONS 请求的响应,它就会发送 POST 请求。

回答by Mark McDonald

I've fixed this issue using an entirely-Apache based solution. In my vhost / htaccess I put the following block:

我已经使用完全基于 Apache 的解决方案解决了这个问题。在我的 vhost / htaccess 中,我放置了以下块:

# enable cross domain access control
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS"

# force apache to return 200 without executing my scripts
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule .* / [R=200,L]

You may not need the latter part, depending on what happens when Apache executes your target script. Credit goes to the friendly ServerFault folkfor the latter part.

您可能不需要后面的部分,这取决于 Apache 执行您的目标脚本时会发生什么。幸得友好ServerFault民间后者的一部分。

回答by Chad Clark

This PHP at the top of the responding script seems to work. (With Firefox 3.6.11. I have not yet done a lot of testing.)

响应脚本顶部的这个 PHP 似乎可以工作。(使用 Firefox 3.6.11。我还没有做过很多测试。)

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Max-Age: 1000');
if(array_key_exists('HTTP_ACCESS_CONTROL_REQUEST_HEADERS', $_SERVER)) {
    header('Access-Control-Allow-Headers: '
           . $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']);
} else {
    header('Access-Control-Allow-Headers: *');
}

if("OPTIONS" == $_SERVER['REQUEST_METHOD']) {
    exit(0);
}

回答by Slav

I had same problem with sending requests to google maps, and solution is quite simple with jQuery 1.5 - for dataType use dataType: "jsonp"

我在向谷歌地图发送请求时遇到了同样的问题,使用 jQuery 1.5 的解决方案非常简单 - 用于数据类型 dataType: "jsonp"

回答by thinkhy

Culprit is preflight request using OPTIONS method

罪魁祸首是使用 OPTIONS 方法的预检请求

For HTTP request methods that can cause side-effects on user data (in particular, for HTTP methods other than GET, or for POST usage with certain MIME types), the specification mandates that browsers "preflight" the request, soliciting supported methods from the server with an HTTP OPTIONS request method, and then, upon "approval" from the server, sending the actual request with the actual HTTP request method.

对于可能对用户数据产生副作用的 HTTP 请求方法(特别是对于 GET 以外的 HTTP 方法,或者对于某些 MIME 类型的 POST 使用),规范要求浏览器“预检”请求,从服务器使用 HTTP OPTIONS 请求方法,然后在服务器“批准”后,使用实际的 HTTP 请求方法发送实际请求。

Web specification refer to: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

Web 规范参考:https: //developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

I resolved the problem by adding following lines in Nginx conf.

我通过在 Nginx conf 中添加以下几行解决了这个问题。

    location / {
               if ($request_method = OPTIONS ) {
                   add_header Access-Control-Allow-Origin  "*";
                   add_header Access-Control-Allow-Methods "POST, GET, PUT, UPDATE, DELETE, OPTIONS";
                   add_header Access-Control-Allow-Headers "Authorization";
                   add_header Access-Control-Allow-Credentials  "true";
                   add_header Content-Length 0;
                   add_header Content-Type text/plain;
                   return 200;
               }
    location ~ ^/(xxxx)$ {
                if ($request_method = OPTIONS) {
                    rewrite ^(.*)$ / last;
                }
    }

回答by thinkhy

I was looking through source 1.3.2, when using JSONP, the request is made by building a SCRIPT element dynamically, which gets past the browsers Same-domain policy. Naturally, you can't make a POST request using a SCRIPT element, the browser would fetch the result using GET.

我正在查看源代码 1.3.2,当使用 JSONP 时,请求是通过动态构建 SCRIPT 元素发出的,该元素通过浏览器的同域策略。当然,您不能使用 SCRIPT 元素发出 POST 请求,浏览器将使用 GET 获取结果。

As you are requesting a JSONP call, the SCRIPT element is not generated, because it only does this when the Type of AJAX call is set to GET.

当您请求 JSONP 调用时,不会生成 SCRIPT 元素,因为它仅在 AJAX 调用的类型设置为 GET 时才会生成。

http://dev.jquery.com/ticket/4690

http://dev.jquery.com/ticket/4690

回答by fboiton

We had a problem like this with ASP.Net. Our IIS was returning an Internal Server Error when trying to execute a jQuery $.postto get some html content due to PageHandlerFactory was restricted to respond only GET,HEAD,POST,DEBUGVerbs. So you can change that restriction adding the verb "OPTIONS" to the list or selecting "All Verbs"

我们在 ASP.Net 上遇到了这样的问题。我们的 IIS 在尝试执行 jQuery$.post以获取一些 html 内容时返回内部服务器错误,因为 PageHandlerFactory 被限制为仅响应GET,HEAD,POST,DEBUG动词。因此,您可以更改该限制,将动词“OPTIONS”添加到列表中或选择“所有动词”

You can modify that in your IIS Manager, selecting your website, then selecting Handler Mappings, double click in your PageHandlerFactory for *.apx files as you need (We use Integrated application pool with framework 4.0). Click on Request Restrictions, then go to Verbs Tabn and apply your modification.

您可以在您的 IIS 管理器中修改它,选择您的网站,然后选择处理程序映射,根据需要双击您的 PageHandlerFactory 以获取 *.apx 文件(我们使用带有框架 4.0 的集成应用程序池)。单击请求限制,然后转到动词选项卡并应用您的修改。

Now our $.postrequest is working as expected :)

现在我们的$.post请求按预期工作:)

回答by Elzo Valugi

I seems that if o.url = 'index.php'and this file exists is ok and returning a success message in the console. It returns an error if I use url:http://www.google.com

我似乎如果o.url = 'index.php'并且此文件存在就可以并在控制台中返回成功消息。如果我使用 url,它会返回一个错误:http://www.google.com

If doing a post request why not using directly the $.postmethod:

如果执行 post 请求,为什么不直接使用$.post方法:

$.post("test.php", { func: "getNameAndTime" },
    function(data){
        alert(data.name); // John
        console.log(data.time); //  2pm
    }, "json");

It is so much simpler.

它简单得多。