jQuery 为什么我收到的是 OPTIONS 请求而不是 GET 请求?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1256593/
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 11:01:08  来源:igfitidea点击:

Why am I getting an OPTIONS request instead of a GET request?

jqueryxmlhttprequesthttp-gethttp-options-method

提问by Paul Tarjan

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js" type="text/javascript"></script>
<script>
$.get("http://example.com/", function(data) {
     alert(data);
});
</script>

it does an OPTIONS request to that URL, and then the callback is never called with anything.

它向该 URL 发出 OPTIONS 请求,然后从不使用任何东西调用回调。

When it isn't cross domain, it works fine.

当它不是跨域时,它工作正常。

Shouldn't jQuery just make the call with a <script>node and then do the callback when its loaded? I understand that I won't be able to get the result (since it is cross domain), but that's OK; I just want the call to go through. Is this a bug, or am I doing something wrong?

jQuery 不应该只是使用<script>节点进行调用,然后在加载时进行回调吗?我知道我将无法获得结果(因为它是跨域的),但是没关系;我只是想让电话通过。这是一个错误,还是我做错了什么?

回答by arturgrigor

According to MDN,

根据MDN

Preflighted requests

Unlike simple requests (discussed above), "preflighted" requests first send an HTTP OPTIONS request header to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests are preflighted like this since they may have implications to user data. In particular, a request is preflighted if:

  • It uses methods other than GET or POST. Also, if POST is used to send request data with a Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain, e.g. if the POST request sends an XML payload to the server using application/xml or text/xml, then the request is preflighted.
  • It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)

预检请求

与简单请求(上面讨论过)不同,“预检”请求首先向其他域上的资源发送 HTTP OPTIONS 请求标头,以确定实际请求是否可以安全发送。跨站点请求是这样预检的,因为它们可能会对用户数据产生影响。特别是,在以下情况下对请求进行预检:

  • 它使用 GET 或 POST 以外的方法。此外,如果 POST 用于发送内容类型不是 application/x-www-form-urlencoded、multipart/form-data 或 text/plain 的请求数据,例如,如果 POST 请求向服务器发送 XML 负载使用 application/xml 或 text/xml,然后预检请求。
  • 它在请求中设置自定义标头(例如,请求使用 X-PINGOTHER 等标头)

回答by Derek Soike

If you're trying to POST

如果你想POST

Make sure to JSON.stringifyyour form data and send as text/plain.

确保JSON.stringify您的表单数据并作为text/plain.

<form id="my-form" onSubmit="return postMyFormData();">
    <input type="text" name="name" placeholder="Your Name" required>
    <input type="email" name="email" placeholder="Your Email" required>
    <input type="submit" value="Submit My Form">
</form>


function postMyFormData() {

    var formData = $('#my-form').serializeArray();
    formData = formData.reduce(function(obj, item) {
        obj[item.name] = item.value;
        return obj;
    }, {});
    formData = JSON.stringify(formData);

    $.ajax({
        type: "POST",
        url: "https://website.com/path",
        data: formData,
        success: function() { ... },
        dataType: "text",
        contentType : "text/plain"
    });
}

回答by VoteyDisciple

I don't believe jQuery will just naturally do a JSONP request when given a URL like that. It will, however, do a JSONP request when you tell it what argument to use for a callback:

我不相信 jQuery 会在给定这样的 URL 时自然地执行 JSONP 请求。但是,当您告诉它用于回调的参数时,它将执行 JSONP 请求:

$.get("http://metaward.com/import/http://metaward.com/u/ptarjan?jsoncallback=?", function(data) {
     alert(data);
});

It's entirely up to the receiving script to make use of that argument (which doesn't have to be called "jsoncallback"), so in this case the function will never be called. But, since you stated you just want the script at metaward.com to execute, that would make it.

完全由接收脚本使用该参数(不必称为“jsoncallback”),因此在这种情况下永远不会调用该函数。但是,既然你说你只想执行 metaward.com 上的脚本,那就可以了。

回答by Adrián Navarro

In fact, cross-domain AJAX (XMLHttp) requests are not allowed because of security reasons (think about fetching a "restricted" webpage from the client-side and sending it back to the server – this would be a security issue).

实际上,出于安全原因,不允许跨域 AJAX (XMLHttp) 请求(考虑从客户端获取“受限”网页并将其发送回服务器 - 这将是一个安全问题)。

The only workaround are callbacks. This is: creating a new script object and pointing the src to the end-side JavaScript, which is a callback with JSON values (myFunction({data}), myFunction is a function which does something with the data (for example, storing it in a variable).

唯一的解决方法是回调。这是:创建一个新的脚本对象并将 src 指向端侧 JavaScript,这是一个带有 JSON 值的回调 (myFunction({data}),myFunction 是一个对数据执行某些操作的函数(例如,存储它)在一个变量中)。

回答by David Lopes

Just change the "application/json" to "text/plain" and do not forget the JSON.stringify(request):

只需将“application/json”更改为“text/plain”,不要忘记 JSON.stringify(request):

var request = {Company: sapws.dbName, UserName: username, Password: userpass};
    console.log(request);
    $.ajax({
        type: "POST",
        url: this.wsUrl + "/Login",
        contentType: "text/plain",
        data: JSON.stringify(request),

        crossDomain: true,
    });

回答by fivebit

I had the same problem. My fix was to add headers to my PHP script which are present only when in dev environment.

我有同样的问题。我的解决方法是将标头添加到我的 PHP 脚本中,这些标头仅在开发环境中出现。

This allows cross-domain requests:

这允许跨域请求:

header("Access-Control-Allow-Origin: *");

This tells the preflight request that it is OK for the client to send any headers it wants:

这告诉预检请求客户端可以发送它想要的任何标头:

header("Access-Control-Allow-Headers: *");

This way there is no need to modify the request.

这样就不需要修改请求了。

If you have sensitive data in your dev database that might potentially be leaked, then you might think twice about this.

如果您的开发数据库中有可能被泄露的敏感数据,那么您可能会三思而后行。

回答by GarDavis

In my case, the issue was unrelated to CORS since I was issuing a jQuery POST to the same web server. The data was JSON but I had omitted the dataType: 'json' parameter.

就我而言,该问题与 CORS 无关,因为我向同一 Web 服务器发出 jQuery POST。数据是 JSON,但我省略了 dataType: 'json' 参数。

I did not have (nor did I add) a contentType parameter as shown in David Lopes' answer above.

我没有(也没有添加)一个 contentType 参数,如上面 David Lopes 的回答所示。

回答by obai

I was able to fix it with the help of following headers

我能够在以下标题的帮助下修复它

Access-Control-Allow-Origin
Access-Control-Allow-Headers
Access-Control-Allow-Credentials
Access-Control-Allow-Methods

If you are on Nodejs, here is the code you can copy/paste.

如果您使用 Nodejs,这里是您可以复制/粘贴的代码。

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin','*');
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH');
  next();
});

回答by helloandre

It's looking like Firefox and Opera (tested on mac as well) don't like the cross domainness of this (but Safari is fine with it).

看起来 Firefox 和 Opera(也在 mac 上测试过)不喜欢这种跨域(但 Safari 对此很好)。

You might have to call a local server side code to curl the remote page.

您可能需要调用本地服务器端代码来卷曲远程页面。