Chrome中的AJAX发送OPTIONS而不是GET / POST / PUT / DELETE?

时间:2014-02-14 15:20:27

标签: jquery ajax cross-domain

我正在开发一个内部Web应用程序。在IE10中,请求工作正常,但在Chrome中,所有AJAX请求(有很多)都是使用OPTIONS发送的,而不是我给出的任何定义的方法。从技术上讲,我的请求是“跨域”。该站点在localhost:6120上提供,我正在向AJAX请求的服务在57124上。This closed jquery bug定义了问题,但不是真正的修复。

如何在ajax请求中使用正确的http方法?

编辑:

这是每页的文档加载:

jQuery.support.cors = true;

每个AJAX都是以类似方式构建的:

var url = 'http://localhost:57124/My/Rest/Call';
$.ajax({
    url: url,
    dataType: "json",
    data: json,
    async: true,
    cache: false,
    timeout: 30000,
    headers: { "x-li-format": "json", "X-UserName": userName },
    success: function (data) {
        // my success stuff
    },
    error: function (request, status, error) {
        // my error stuff
    },
    type: "POST"
});

10 个答案:

答案 0 :(得分:124)

Chrome正在预检查找CORS标头的请求。如果请求是可接受的,它将发送实际请求。如果您正在执行此跨域,您只需处理它,或者找到一种方法来使请求成为非跨域。这就是为什么jQuery bug被关闭为不能修复的原因。这是设计的。

  

与简单请求(如上所述)不同,首先是“预检”请求   通过OPTIONS方法向该资源发送HTTP请求   其他域,以确定实际请求是否安全   发送。跨站请求是这样的预检,因为它们可能   对用户数据有影响。特别是,请求是   预防如果:

     
      
  • 它使用GET,HEAD或POST以外的方法。此外,如果使用POST来发送具有除以外的Content-Type的请求数据   application / x-www-form-urlencoded,multipart / form-data或text / plain,   例如如果POST请求使用XML向服务器发送XML有效负载   application / xml或text / xml,然后请求被预检。
  •   
  • 它在请求中设置自定义标头(例如,请求使用标头,例如X-PINGOTHER)
  •   

答案 1 :(得分:15)

基于请求未在默认端口80/443上发送的事实,此Ajax调用自动被视为跨源资源(CORS)请求,换句话说,这意味着请求会自动发出一个OPTIONS请求,检查服务器/ servlet端的CORS头。

即使您设置了

,也会发生这种情况
crossOrigin: false;

或者即使你省略它。

原因很简单就是localhost != localhost:57124。尝试仅将其发送到没有端口的localhost - 它将失败,因为请求的目标将无法访问,但请注意,如果域名相等,请求将在没有POST之前的OPTIONS请求。

答案 2 :(得分:3)

我同意Kevin B,错误报告说明了一切。听起来你正试图进行跨域的ajax调用。如果您不熟悉相同的原始政策,可以从这里开始:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Same_origin_policy_for_JavaScript

如果这不是一个跨域的ajax调用,请尝试使您的目标网址相对,并查看问题是否消失。如果你真的绝望地看看JSONP,但要注意,混乱潜伏。我们真的无法帮助你。

答案 3 :(得分:1)

If it is possible pass the params through regular GET/POST with a different name and let your server side code handles it.

I had a similar issue with my own proxy to bypass CORS and I got the same error of POST->OPTION in Chrome. It was the $username = htmlentites($_POST["username"]); if (!filter_var($email, FILTER_VALIDATE_EMAIL) === false) { //Bad email, so something else. die('...'); } $email = $_POST["emailadd"]; header in my case (Authorization and "x-li-format" here in your case.) I ended up passing it in a dummy format (e.g. "X-UserName" in GET) and I changed the code for my proxy to turn that into a header when making the call to the destination. Here it is in PHP:

AuthorizatinJack

答案 4 :(得分:1)

在我的情况下,我正在调用由AWS(API网关)托管的API。当我尝试从API自己的域以外的域调用API时发生错误。由于我是API所有者,因此我在测试环境中启用了CORS,如Amazon Documentation中所述。

在生产中,此错误不会发生,因为请求和api将位于同一个域中。

我希望它有所帮助!

答案 5 :(得分:0)

@Dark Falcon的answered,我只是处理它

在我的情况下,我正在使用node.js服务器,并且如果它不存在则创建会话。由于OPTIONS方法中没有会话详细信息,因此最终为每个POST方法请求创建了一个新会话。

所以在我的app例程中创建会话 - 如果不存在,我只是添加了一个检查以查看方法是否为OPTIONS,如果是,只需跳过会话创建部分:

    app.use(function(req, res, next) {
        if (req.method !== "OPTIONS") {
            if (req.session && req.session.id) {
                 // Session exists
                 next();
            }else{
                 // Create session
                 next();
          }
        } else {
           // If request method is OPTIONS, just skip this part and move to the next method.
           next(); 
        }
    }

答案 6 :(得分:0)

考虑使用axios

axios.get( url,
{ headers: {"Content-Type": "application/json"} } ).then( res => {

  if(res.data.error) {

  } else { 
    doAnything( res.data )
  }

}).catch(function (error) {
   doAnythingError(error)
});

我使用fetch解决了这个问题,并且axios工作得很好。

答案 7 :(得分:0)

我遇到了一个非常类似的问题。我花了将近半天的时间来理解为什么一切都在Firefox中正常运行并且在Chrome中失败。在我的情况下,这是因为我的请求标题中存在重复(或可能是错误的)字段。

答案 8 :(得分:0)

使用fetch代替XHR,这样即使跨域请求也不会被预显示。

答案 9 :(得分:-1)

 $.ajax({
            url: '###',
            contentType: 'text/plain; charset=utf-8',
            async: false,
            xhrFields: {
                withCredentials: true,
                crossDomain: true,
                Authorization: "Bearer ...."
            },

            method: 'POST',

            data: JSON.stringify( request ),
            success: function (data) {
                console.log(data);
            }
        });

contentType:'text / plain; charset = utf-8'或仅contentType:'text / plain'对我有用! 问候!