This scenario uses Access-Control-Allow-Credentials alongside the POST method to manage server-side PHP session variables that must remain intact.
For reference, the front-end is a create-react-app project running at http://localhost:3000 and the back-end is PHP running on example.com.
Achieving this with the $.ajax() method is easy and straightforward.
UseAjax(incomingData) {
return new Promise(function(resolve, reject) {
$.ajax({
url: 'http://example.com/api.php',
type: 'post',
data: incomingData,
xhrFields: { withCredentials: true },
success: function(data) {
console.log(data)
}
})
.then((data,status) => {
// Get the result and transform into valid JSON
if ( typeof data === typeof 'str' ) {
try {
data = JSON.parse(data);
} catch(e) {
reject(data,status);
console.log('Exception: ', e);
console.log('API Returned non-JSON result: ', data);
}
}
return data;
}).then((dataObject) => {
console.log('dataObject:');
console.log(dataObject);
resolve(dataObject);
});
});
}
Oddly enough though, when using the fetch() API, it is under the impression that I am not allowing CORS. Of course I have CORS enabled as this request works fine with Ajax and only fails while using the fetch() API.
Here is a look at what I tried while using the fetch() API.
UseFetch(requestData) {
return new Promise(function(resolve, reject) {
console.log('Relay() called with data: ', requestData);
fetch('http://example.com/api.php', {
method: 'POST', // or 'PUT'
body: JSON.stringify(requestData), // data can be `string` or {object}!
headers: new Headers({
'Content-Type': 'application/json'
})
}).then((result) => {
// Get the result
return result.json();
}).then((jsonResult) => {
// Do something with the result
if ( jsonResult.err )
reject(jsonResult);
console.log(jsonResult);
resolve(jsonResult);
});
});
}
It provides this error.
Failed to load http://example.com/: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
On the PHP side, I am using a simple output to ensure nothing else is going wrong causing the error on the server's side.
<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: http://example.com');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Headers: Content-Type, Authorization, x-requested-with');
echo json_encode(['data'=>'result']);
?>
I have followed many questions, but most notably this question with a very thorough explanation of the issue and possible solutions.
For now, I am just using the tried-and-true $.ajax() to complete this task, but I am wanting to fully understand the fetch() API to the extent necessary to replicate this functionality as it seems like something very basic from my experience.
In your PHP code, you've specified header('Access-Control-Allow-Origin: http://example.com');. This is wrong - you need to specify the value passed in the Origin request header (which in your case would be http://localhost:3000):
header('Access-Control-Allow-Origin: http://localhost:3000');
Ideally you wouldn't hardcode it - you'd just extract the Origin request header and pass that back.
BTW, I believe that JQuery's $.Ajax uses fetch() under the covers (just like XmlHTTPRequest()). Basically, everything uses fetch...
Related
hi guys i'm getting stuck in my code i'm requesting to a php api to get data with using jquery ajax. please help me with a solution
Ajax code
$.ajax({
url: request_url+"courses.php",
type: 'POST',
dataType: 'jsonp',
cors: true ,
contentType:'application/json',
data: { request_courses: courses },
secure: true,
headers: {
'Access-Control-Allow-Origin': '*',
},
beforeSend: function (xhr) {
xhr.setRequestHeader ("Authorization", "Basic " + btoa(""));
},
success: function (data){
console.log("helo "+data);
}
});
Php Api code
if(isset($_POST['request_courses'])){
$courses = mysqli_query($conn, "SELECT * FROM `courses`");
while ($rows = mysqli_fetch_assoc($courses)) {
$data[] = $rows;
}
echo json_encode(array('status' => 1,'message'=>'responce_courses','data'=>$data));
}
Error While runing this code
courses.html:1 A cookie associated with a cross-site resource at http://localhost/ was set
without the `SameSite` attribute. A future release of Chrome will only deliver cookies with
cross-site requests if they are set with `SameSite=None` and `Secure`. You can review
cookies in developer tools under Application>Storage>Cookies and see more details at
https://www.chromestatus.com/feature/5088147346030592 and
https://www.chromestatus.com/feature/5633521622188032.
Access to XMLHttpRequest at 'file:///home/punkaj/Music/Cordova/ithub/www/index.html' from
origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for
protocol schemes: http, data, chrome, chrome-extension, https.
jquery.js:2 GET file:///home/punkaj/Music/Cordova/ithub/www/index.html net::ERR_FAILED
send # jquery.js:2
ajax # jquery.js:2
h # plugins.js:45
i # plugins.js:45
dispatch # jquery.js:2
y.handle # jquery.js:2
First off, are you sure of the file URLs? 'file:///home/punkaj/Music/Cordova/ithub/www/index.html' seems a bit sketchy IMO. Make sure that it's correct.
And secondly, looks like the AJAX referenced file (courses.php) is trying to set a new cookie on the browser, which is a bad practice in REST APIs. It's better to just return/output whatever value you want, and when you have that value in your 'success' AJAX function, you can save it there as a cookie back in the original script.
Lastly, it looks like you're getting the file directly by using an FTP protocol (file:///) rather than an HTTP protocol (http://) to get the content of the HTML file. Can't provide any further assistance on that without seeing the source code
I am trying to fetch some JSON data. I can access the data just fine in a regular web browser, like this: http://www.ebrent.net/apis/tsp.php?fund=G+Fund&start=2003-01-01&end=2004-01-01, but I cannot get it to work in jQuery. What am I doing wrong?
Please take a look at my jsFiddle: https://jsfiddle.net/MrSnrub/mq31hwuj/
var tsp_api = '//www.ebrent.net/apis/tsp.php?start=2003-01-01&end=2004-01-01';
$.getJSON( tsp_api, function(json) {
// This alert never gets called.
alert("Success!");
// Set the variables from the results array
var data = json;
// console.log('Data : ', data);
// Set the div's text
$('#div-data').text(data);
});
You cannot get the result because the remote site doesn't have CORS enabled:
If you look at the console, you'll see:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at
http://www.ebrent.net/apis/tsp.php?start=2003-01-01&end=2004-01-01.
(Reason: CORS header 'Access-Control-Allow-Origin' missing).
You can bypass CORS by using something like anyorigin.com, i.e.:
$.getJSON('http://anyorigin.com/get/?url=http%3A//www.ebrent.net/apis/tsp.php%3Fstart%3D2003-01-01%26end%3D2004-01-01&callback=?', function(data){
$('#div-data').html(data.contents);
});
This works if you run the your server without using https. Note fetchApi was used instead of jquery Library as its not readily available in the browser
var tsp_api = 'https://www.ebrent.net/apis/tsp.php?start=2003-01-01&end=2004-01-01';
function fetchData(url) {
return fetch(url, {
method: 'get'
}).then(function(response) {
return response.json();
}).catch(function(err) {
console.log(error);
});
}
fetchData(tsp_api).then((data)=> console.log(data)).catch((err)=> console.log(err));
This won't work on jsfiddle using HTTPS, the browser will refuse to load any resources over HTTP. As you've tried, changing the API URL to have HTTPS instead of HTTP typically resolves this issue. However, your ebrent.net did not allow CoRS for HTTPS connections. Because of this, you won't be able to get your result for jsfiddle
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)
Im trying to make a request from one server to another with json and php.
my html page:
$.ajax({
type: "POST",
url: "https://api.domain.com/gateway/partners/create_account.ajax.php",
dataType: 'jsonp',
crossDomain: true,
data: { "name" : "Test name"},
success: function(data)
{
console.log(data.responseText);
}
});
My php looks like this:
$name = $_GET['name'];
$data = array("Hello", $name);
echo json_encode($data);
I want to receive on my console: Hello Test name
What did I do wrong?
You are:
Telling jQuery to process the response as JSONP
Writing PHP that will output JSON (not JSONP) … presumably with a text/html content-type.
Trying to make a POST request instead of a GET request. JSONP only supports GET.
Trying to treat the data returned by the request as if it were an XHR object.
The minimal example of a JSONP response would be:
<?php
header("Content-Type: application/javascript");
$name = $_GET['name'];
$data = array("Hello", $name);
echo $_GET['callback'];
echo "(";
echo json_encode($data);
echo ");";
Then you need to alter the JS so that type: "POST" becomes type: "GET" and console.log(data.responseText); becomes console.log(data);
Alternatively, you could use another technique to bypass the same origin policy and still use POST.
The jsonp is a old practice and a insecure one because any one can call to your script. To is very default tor retrieving errors when a jsonp call fails.
You can implement CORS headers in your request, and then you can use just a simple XHR call.
Addeding the header:
Access-Control-Allow-Origin: *
Will fix your issue, but is better use the exact domain instead of the wildcard.
I am trying to request JSON from Google Places API, but I am still getting the cross-domain request error after firstly including:
<?php
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Methods: POST, GET");
header("Access-Control-Allow-Headers: x-requested-with");
?>
The JSON request I am using is standard JQuery:
function load() {
var url = 'https://maps.googleapis.com/maps/api/place/details/json?reference=CnRhAAAARMUGgu2CeASdhvnbS40Y5y5wwMIqXKfL-n90TSsPvtkdYinuMQfA2gZTjFGuQ85AMx8HTV7axABS7XQgFKyzudGd7JgAeY0iFAUsG5Up64R5LviFkKMMAc2yhrZ1lTh9GqcYCOhfk2b7k8RPGAaPxBIQDRhqoKjsWjPJhSb_6u2tIxoUsGJsEjYhdRiKIo6eow2CQFw5W58&sensor=true&key=xxxxxxxxxxxxxx';
$.ajax(url, {
async: true,
success: function(data, textStatus, jqXHR) {
dump(data);
}
});
}
I would use a JSONP query instead, but the Google Places API doesn't support JSONP...how can I solve this? With a proxy server? I am not sure how to go about this or what I'm doing wrong.
The URL you are requesting data from has to grant permission with access control headers. It would defeat the object of the same origin policy is a remote origin could grant permission to itself!
If the API you are using doesn't provide a JSON-P API, and doesn't set access control headers itself, then you need to use a proxy. Either one you run yourself, or a third party one that will convert to JSON-P (such as YQL).