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
jQuery $.ajax(), $.post sending "OPTIONS" as REQUEST_METHOD in Firefox
提问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_TYPE
on 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
回答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 时才会生成。
回答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 $.post
to get some html content due to PageHandlerFactory was restricted to respond only GET,HEAD,POST,DEBUG
Verbs. 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 $.post
request 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.
它简单得多。