AJAX call:
$.ajax({
url: "http://myserver2:296/api/Demo/HelloWorld",
type: "GET",
dataType: 'JSONP',
jsonp: "callback",
headers: { 'API_KEY': 'mykey09090' },
success: function (result) {
console.log(result);
},
error: ajaxFailed
});
function ajaxFailed(xmlRequest) {
alert(xmlRequest.status + ' \n\r ' +
xmlRequest.statusText + '\n\r' +
xmlRequest.responseText);
}
I get the following error: Failed to load resource: the server responded with a status of 403 (Forbidden). However when I use Postman, I just have to add the headers with the http://myserver2:296/api/Demo/HelloWorld url it returns the string.
Can I please get some assistance to resolve the issue.
My goal, is to allow the origin server along with the API key correctly provided to get the data back from the Web Api.
Adding the API_KEY header to the request triggers your browser to first send a CORS preflight OPTIONS request. Any headers you add to a request other than headers defined as CORS-safelisted request-headers will trigger your browser to send a CORS preflight OPTIONS request.
I can’t tell for sure but it seems like the 403 you’re seeing is from your server responding to that OPTIONS request, and saying it doesn’t expect to get OPTIONS requests and doesn’t allow them.
The reason you don’t get this from Postman is that unlike browser engines, Postman does not implement CORS, so it does not send the OPTIONS request. (Postman does not operate under the same-origin Web-security model that browsers enforce for Web applications.)
So to make your client app work as expected for scripted cross-origin access to that server, you must configure the server to respond in the right way to that CORS preflight OPTIONS request.
Related
I have a REST api made in Laravel 5.1 hosted in a remote server. Now, I', trying to consume that API from another website (that I have in local).
In Laravel I set the required lines to send the CORS headers. I also tested the API using Postman and everything seems to be ok!
In the Frontend
Then, in the website I sent the POST request using ajax, with this code:
var url="http://xxx.xxx.xxx.xxx/apiLocation";
var data=$("#my-form").serialize();
$.ajax({
type: "POST",
url: url,
data: data,
headers: { 'token': 'someAPItoken that I need to send'},
success: function(data) {
console.log(data);
},
dataType: "json",
});
Buy then I get this error in the console:
XMLHttpRequest cannot load http://xxx.xxx.xxx.xxx/apiLocation.
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' is therefore not allowed access.
In the Backend
In the API I set this (using a Laravel Middleware to set the headers):
return $next($request)
->header('Access-Control-Allow-Origin', '*')
->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
So, I'm confused about where is exactly the problem.
In the server? but then why with Postman work fine?
Is in the Ajax call? so, then what should I add?
Your backend code must include some explicit handling for OPTIONS requests that sends a 200 response with just the configured headers; for example:
if ($request->getMethod() == "OPTIONS") {
return Response::make('OK', 200, $headers);
}
The server-side code also must send an Access-Control-Allow-Headers response header that includes the name of the token request header your frontend code is sending:
-> header('Access-Control-Allow-Headers', 'token')
but then why with Postman work fine?
Postman isn’t a web app and isn’t bound by same-origin restrictions placed on web apps by browsers to block them from making cross-origin requests. Postman is a browser bolt-on for convenience of testing requests in the same way they could be made outside the browser using curl or whatever from the command line. Postman can freely make cross-origin requests.
https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS in contrast explains how browsers block web apps from making cross-origin requests but also how you can un-block browsers from doing that by configuring your backend to send the right CORS headers.
https://developer.mozilla.org/docs/Web/HTTP/Access_control_CORS#Preflighted_requests explains why the browser is sending that OPTIONS request your backend needs to handle.
Code dump:
$.ajax({
type: 'GET',
dataType: 'json',
url: api,
xhrFields: {
withCredentials: true
},
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', "Basic [my auth token]");
},
success: function(jd) {
console.log(jd.stringify());
}
});
The problem is that Chrome and Firefox send an OPTIONS preflight when I include a beforeSend, however that OPTIONS request is refused by the API because it doesn't know how to handle an OPTIONS request and treats it like a GET, sees no Authorization header and refuses the request.
The only way I can get this to work is to coerce the browser either to not send an OPTIONS request or include my header with it. I am unable to modify the API that I am using.
I would appreciate it if anyone could advise me.
The reason why browser sends preflight request is that you are using custom headers. Please. read about how to avoid preflight request (content type should be text or html and no custom headers)
If you could not chagne server side the last chance to make it work is to create your custom proxy (for example you can create node server and that node app would take your requests and forward them to those Api Then you will have you own server even in the some domain and this proxy server will send CORS requests to another server domain.
I'm using http://smmry.com/api for a small project. I'm fairly new to AJAX and have trouble using it. Here's what I have so far:
var a = $.ajax({
type:'POST',
url:'http://api.smmry.com/&SM_API_KEY=XXXXXXXX',
headers: {'Authorization': '["Expect:"]'},
data: {'SM_URL':'https://en.wikipedia.org/wiki/Human%E2%80%93computer_interaction'},
contentType:'application/json',
dataType: 'json',
});
console.log(a);
The error I'm getting:
XMLHttpRequest cannot load http://api.smmry.com/&SM_API_KEY=XXXXXXXX. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
I'm fairly sure it has something to do with headers. I have no idea what to do and would really appreciate it if someone could help me!
The error you are getting has to do with CORS. The XMLHttpRequest sends a preflight request, which is not supported by the SMMRY API, and is something that needs to be enabled server side. What can you do instead?
You can talk to their API through a server, e.g. a simple Node server.
You then send the XMLHttpRequest to your own server, where you do allow preflight request by allowing CORS (this is a simple line of code in a Node / Express server), and you forward the request to the SMMRY API and send the response back to your site. This process is called "proxying".
I have been working on a personal webapp and have hit a little snag. My API calls only work for some APIs and not for others. For the ones it doesn't work with I will usually get an error message like so.
XMLHttpRequest cannot load https://api.meetup.com/2/cities. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
After doing some research I know it is to do with CORS not being setup. I was wondering if it would be possible to set this up in the client when making an AJAX request. The current way I am doing this is like so
var handleRequest = function(request){
$.ajax({
type: "GET",
url: request,
success: function(data) {
var rawJSON = JSON.stringify(data, null, 2);
editor.setValue(rawJSON);
},
dataType: 'json'
});
The server you're trying to access has to grant you permission to access it. An IT admin has to provide you with a URL that grants you permission to hit their external server. The server you are trying to hit has to setup CORS. http://enable-cors.org/
According to their docs they support JSONP.
https://www.meetup.com/meetup_api/
This is your way around CORS.
I have a URL, which gives response on browser:
https://api.sandbox.paypal.com/retail/merchant/v1/locations
It gives:
{
"errorCode": 600031,
"message": "Missing access token",
"developerMessage": "You must provide an access token when calling this API. It can be passed as either a header of the form \"Authorization: Bearer \" or as a query parameter called access_token.",
"errorType": "oauth/missing_access_token",
"correlationId": "4de95cd8aa090"
}
I tried this:
$.ajax({
url: "https://api.sandbox.paypal.com/retail/merchant/v1/locations",
dataType: 'json',
type: 'POST',
success: function (data) {
console.log(data);
alert("success", data);
},
error: function (data) {
alert("fail", data);
console.log(data);
alert("Sorry..Please try again later");
},
});
But I am not getting the same response as I am getting on browser. I am getting error.
Please check here
http://jsfiddle.net/ajitksharma/wehGy/
However while debugging on Browser console I got the error:
XMLHttpRequest cannot load https://api.sandbox.paypal.com/retail/merchant/v1/locations. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
You can make AJAX calls to a backend API which is on another domain, however, it needs to return JSONP format and not just JSON, otherwise you get and error. This is due to same origin policy: https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy.
This discussion may be helpful to understand JSONP: Can anyone explain what JSONP is, in layman terms?
Since you don't have control over PayPal's API and you can't ask them to return JSONP to you, these requests to PayPal's API need to be done from the server-side script of your application.
Running this from any other location, for example JSFiddle, will give you the Access-Control-Allow-Origin error since you're making a cross-domain request. Please read further about the same-origin policy.
As for the first error, its because your request needs an API key from paypal. See this page about getting an API key and making a simple request.
As Lisa Stoz and kaminari suggested it is not possible to call a service in another domain without some patch work. Now as you see the response when you hit that url via browser it says you need to add an extra header to your ajax request something like 'authorisation'