Reputation: 4609
I'm trying to do an AJAX request to https://developers.zomato.com/api/v2.1/search referring to Zomato API
The server has headers:
"access-control-allow-methods": "GET, POST, DELETE, PUT, PATCH, OPTIONS",
"access-control-allow-origin": "*"
The problem is that the API requires additional headers set for user-key. But whenever I set custom headers then chrome would do a pre-flight request by sending an OPTIONS request to the above URL which is failing, and thus the AJAX request is failing as well.
If I don't set the headers, then I don't get a CORS error, but rather a forbidden error from server since I'm not setting user-key header.
Any way to go about this catch-22 situation?
Both Jquery and JavaScript way are failing:
$(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);
}
Error I'm getting:
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.
If somebody wants to reproduce you can get a free user-key here: https://developers.zomato.com/api
Upvotes: 3
Views: 7614
Reputation: 15072
You can't bypass Access-Control-Allow-Headers in preflight response
.
However as mentioned by @Jaromanda X in comments, Zomato sends:
Access-Control-Allow-Headers:X-Zomato-API-Key
...meaning you can only send this non-standard header from browser. Also don't go too low-level in request definition when jQuery has pretty and prepared shorthands ...
$.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
}
});
Upvotes: 2
Reputation: 708146
There does not appear to be a work-around for this issue from a browser. The CORS specification requires a browser to preflight the request with the OPTIONS request if any custom headers are required. And, when it does the OPTIONS preflight, it does not include your custom headers because part of what the OPTIONS request is for is to find out what custom headers are allowed to be sent on the request. So, the server is not supposed to require custom headers on the OPTIONS request if it wants this to work from a browser.
So, if the server is requiring the custom headers to be on the OPTIONS request, then the server is just expecting something that will not happen from a browser.
See related answers that describe more about this here:
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
And, another user with the same issue here:
It appears the Zomato is not browser friendly, but requires access from a server where you don't have CORS restrictions.
FYI, the error coming back from Zomato is 501 which means NOT IMPLEMENTED for the OPTIONS command. So, it looks like it's not only that the key is not being sent with the OPTIONS command, but that Zomato does not support the OPTIONS command, but that is required for the use of custom headers on a cross-origin request from a browser.
Upvotes: 2