XMLHttpRequest cannot load : only with headers in Ajax jQuery - php

I try to get JSON data from my own API, from a $.ajax method with jQuery.
I must have a header 'Authorization-api-key' in my request otherwise I'll have a 401 status code.
$.ajax({
type: "GET",
headers: {'Authorization-api-key' : 'key'},
dataType: "json",
crossDomain: true,
url: "http://urlofmyonlineapi.com/api/ressource",
success: function (data) {
alert(data);
}
});
I have read several threads on stackoverflow about CORS and the'XMLHttpRequest cannot load' problem. So, in my API I have added in response these headers (I use Slim Framework):
$app->response->headers->set('Access-Control-Allow-Origin', '*');
$app->response->headers->set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
$app->response->headers->set('Access-Control-Allow-Headers', '*');
$app->response->headers->set('Access-Control-Allow-Credentials', 'true');
The problem
If I put any header in $.ajax with 'headers: {...}' argument, I have two errors in my browser console:
'OPTIONS' error
'XMLHttpRequest cannot load' error
If I remove headers, I haven't error but I have my 401 status code.
If I remove headers AND my API's authentification with the key in request's headers, I get my data.

I have solved the problem: my API didn't accept OPTIONS request.
(Ajax with jQuery need to make an OPTIONS pre-request)

Related

jQuery AJAX http GET cross domain - required headers in response

I've made a web application running on domain http://app.mydomain.tld
and I've APIs on https://api.mydomain.tld (APIs are not developed by me).
I'm doing an AJAX HTTPs GET call with jQuery using this method:
$.ajax({
url: "https://api.mydomain.tld/GetSomething/read.php",
method: "GET",
contentType:"application/json; charset=utf-8",
dataType:"json",
async:false,
headers: {"Accept": "application/json; odata=verbose" },
success: function (data) { doSomething(); },
error: function (data) { showError(); }
});
This call is returning an error like NetworkError: failed to execute 'send' on 'XMLHttpRequest': Failed to load 'https://api.mydomain.tld/GetSomething/read.php'.
I've added the Access-Control-Allow-Origin extension for Chrome and the call is working fine.
So I've checked response headers. When Chrome extension is NOT enabled I've this response headers:
Access-Control-Allow-Origin: *
When the extension is enabled I've these headers:
Access-Control-Allow-Headers: access-control-allow-methods,access-control-allow-origin
Access-Control-Allow-Methods: GET, PUT, POST, DELETE, HEAD, OPTIONS
Access-Control-Allow-Origin: *
So my question, that could have an obvious answer, is: are these headers required to make correct cross domain calls?
If yes, do my APIs need the below additional code?
<?php
header("Access-Control-Allow-Origin","*");
header("Access-Control-Allow-Methods","GET, PUT, POST, DELETE, HEAD, OPTIONS");
header("Access-Control-Allow-Headers","access-control-allow-methods,access-control-allow-origin");
?>
Is correct what I said or am I missing something to make my call working without changing APIs code?
PS: if possibile I would not use JSONP.

Custom headers for ajax and php

So, I'm having a problem retrieving custom headers from ajax call.
This is my ajax call:
$.ajax({
url: 'api.php',
type: 'get',
processData: false,
beforeSend: function(xhr) {
xhr.setRequestHeader('HASH', '5c268592cd4db9c7f6b813bb689005c6');
},
success: function(data) {
console.log(data);
},
error: function(xhr, status, error) {
console.log(xhr);
}
});
And in my api.php, I have this:
<?php
$headers = getallheaders();
print_r(json_encode($headers));
the output:
......
"Access-Control-Request-Headers":"content-type,hash",
....
This returns null:
echo $headers['hash'];
// or this echo $headers['HASH'];
You are making a cross-origin request (you shouldn't be, since your code shows a relative URL, but perhaps there is an HTTP redirect in play somewhere) and adding custom headers.
This means that it is not a simple request, but requires a preflight OPTIONS request.
The output you see is the headers of the OPTIONS request asking permission from the server to send the request with the custom headers.
You need to grant that permission, then the browser will make a second request (which is the one you are expecting).
header("Access-Control-Allow-Origin: http://example.com/");
header("Access-Control-Allow-Headers: HASH, Content-Type");
header("Access-Control-Allow-Methods: GET");
Try this $_SERVER["HTTP_HASH"];

Error in CORS ajax request

In php i do echo json_encode($dump);
If echo it out using php i get {"load":"0.64 0.58 0.52 2\/361 12978\n","procs":"8\n"}
Than i make CORS Request using dataType:jsonp
$(function () {
$.ajax({
type: "POST",
ContentType: 'application/json; charset=utf-8',
url: 'http://labs.isaumya.com/loadtest/load',
dataType: "jsonp",
success: function (response) {
console.log(response.data);
},
error: function (xhr, status, error) {
console.log(error);
}
});
});
I get this error on the console:
DEMO
You are dealing with JSON, not JSONP. dataType: "jsonp", should be dataType: "json",
You can remove the data parameter entirely if your server outputs the correct content-type header for JSON (application/json).
JSONP is a hack to work around the Same Origin Policy from before CORS was designed and implemented by browsers. CORS is the modern approach to making cross origin requests. You use it instead of JSONP.
Both CORS and JSONP are technologies that must be supported by the server. http://labs.isaumya.com/loadtest/load doesn't appear to support either. You will have to modify the server if you want it to supply data in JSONP format or grant permission with CORS.
Unrelated to your actual problem:
You have no data parameter so you aren't sending JSON to to the server, remove the ContentType parameter. Since you aren't POSTing any data, you should probably be making a GET request, not a POST request.

CORS not working with JQuery Ajax

I have some JQuery code that logs a user into the system by connecting to my api, which is on a subdomain - api.foo.com
My JQuery code is:
$.ajax({
type: "POST",
crossDomain: true,
url: "http://api.foo.com",
data: {json:"true",com:"login",username:$('#LoginUsername').val(),password:$('#LoginPassword').val()},
dataType: "json",
success: function(Data) {
console.log("Request sent and data received");
console.log(Data);
}
});
The issue is that in the console, I get the error XMLHttpRequest cannot load http://api.foo.com/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://foo.com' is therefore not allowed access.
I know for a fact that I have set the 'Access-Control-Allow-Origin' header to * in my php code - header("Access-Control-Allow-Origin: *"); and I have checked in on google chrome (See screenshot below).
I originally opened a question about this issue but realised I had misspelled the header, whereas this time that is not the case.
The screenshot below is of the headers I receive when I connect to api.foo.com directly.

XMLHttpRequest cannot load url. Method DELETE is not allowed by Access-Control-Allow-Methods

I am trying to make an ajax request to my restserver:
<script>
var id = "104";
var postData = {
'id' : id
};
AJS.$.ajax({
url: "myurl",
crossDomain: true,
data: postData,
type: "DELETE",
// dataType: "json",
success: function(msg, textStatus, jqXHR) {
alert( "Data Saved: " + msg);
}
});
</script>
But I am receiving the following error:
XMLHttpRequest cannot load http ://myurl/rest/controller/resource/id/107. Method DELETE is not allowed by Access-Control-Allow-Methods.
I have added the following at the top of my php controller:
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
header('Access-Control-Allow-Headers', 'x-requested-with');
The only methods it seems to accept is get and post but delete and put create an error.
Any ideas?
Thanks,
James
I learned the hard way the other day that it's pretty much impossible to perform a cross-domain ajax request from just about any browser. I would handle the redirecting HTTP request on the server-side instead. Have this ajax request go to a script on the same url/server, and have that script perform an HTTP request and wait for the data from the other server you're attempting to get data from.

Categories