头文件失败的AJAX请求

时间:2015-11-29 06:48:12

标签: javascript jquery ajax

我正在尝试向https://developers.zomato.com/api/v2.1/search提及Zomato API

的AJAX请求

服务器有标题:

"access-control-allow-methods": "GET, POST, DELETE, PUT, PATCH, OPTIONS",
"access-control-allow-origin": "*"

问题是API需要为用户密钥设置额外的标头。但是每当我设置自定义标题时,chrome就会通过向上面的URL发送OPTIONS请求来执行飞行前请求,这个请求失败了,因此AJAX请求也失败了。

如果我没有设置标题,那么我没有收到CORS错误,而是来自服务器的禁止错误,因为我没有设置用户密钥标题。

任何方式来解决这个问题22?

Jquery和JavaScript方式都失败了:

$(document).ready(function () {

    $.ajax({
        url: 'https://developers.zomato.com/api/v2.1/search',
        headers: {
            'Accept': 'application/json',
            'user_key': 'XXXXX'
        },
        success: function (data) {
            console.log(data);
        }
    });

});



var xhr = new XMLHttpRequest();
var url = 'https://developers.zomato.com/api/v2.1/search';
xhr.open('GET', url, false);

xhr.setRequestHeader('Accept', 'application/json');
xhr.setRequestHeader('user_key', 'XXXXXX');

xhr.send(null);

if (xhr.status == 200) {
    console.log(xhr.responseText);
}

我得到的错误:

OPTIONS https://developers.zomato.com/api/v2.1/search 

XMLHttpRequest cannot load https://developers.zomato.com/api/v2.1/search. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access. The response had HTTP status code 501.

如果有人想要重现,您可以在此处获得免费的用户密钥: https://developers.zomato.com/api

2 个答案:

答案 0 :(得分:2)

浏览器似乎没有针对此问题的解决方法。如果需要任何自定义标头,CORS规范要求浏览器使用OPTIONS请求预检请求。并且,当它执行OPTIONS预检时,它不包括您的自定义标头,因为OPTIONS请求的一部分是找出允许在请求上发送的自定义标头。因此,如果服务器希望从浏览器开始工作,则不应该在OPTIONS请求上要求自定义标头。

因此,如果服务器要求自定义标头位于OPTIONS请求上,那么服务器只是期待浏览器不会发生的事情。

请参阅相关答案,详细说明:

jQuery CORS Content-type OPTIONS

Cross Domain AJAX preflighting failing Origin check

How do you send a custom header in a cross-domain (CORS) XMLHttpRequest?

Using CORS for Cross-Domain Ajax Requests

并且,另一位在此处遇到相同问题的用户:

Zomato api with angular

看来Zomato不是浏览器友好的,但需要从没有CORS限制的服务器进行访问。

仅供参考,从Zomato回来的错误是501,这意味着OPTIONS命令没有实现。因此,看起来它不仅仅是使用OPTIONS命令发送密钥,而且Zomato不支持OPTIONS命令,但这是在浏览器的跨源请求中使用自定义标头所必需的。

答案 1 :(得分:2)

您无法绕过Access-Control-Allow-Headers in preflight response

然而正如@Jaromanda X在评论中提到的那样,Zomato发送:

Access-Control-Allow-Headers:X-Zomato-API-Key

...意味着您只能从浏览器发送此非标准标头。当jQuery有漂亮的准备好的短片时,也不要在请求定义中过低......

TL; DR工作示例:

$.ajax({
  type: "GET", //it's a GET request API
  headers: {
    'X-Zomato-API-Key': 'YOUR_API_KEY' //only allowed non-standard header
  },
  url: 'https://developers.zomato.com/api/v2.1/dailymenu', //what do you want
  dataType: 'json', //wanted response data type - let jQuery handle the rest...
  data: {
     //could be directly in URL, but this is more pretty, clear and easier to edit
     res_id: 'YOUR_RESTAURANT_OR_PLACE_ID',
  },
  processData: true, //data is an object => tells jQuery to construct URL params from it
  success: function(data) {
    console.log(data); //what to do with response data on success
  }
});