Searched all over google and here and tried a few things. The page I've setup can only have Javascript code. I've tried the below for a request to pull some details. It works on Chrome and other browsers just not on Safari. I get a "Failed to load resource: the server responded with a status of 404 ()" on Safari v13.1.
Assuming this needs different headers sending for Safari or CORS is causing some issue. Not sure on this. Have tried the fetch method and that's not worked and given the same problem. I'm sure a lot of people have had this issue and found a fix for it in JavaScript. Any help on this would be greatly appreciated.
XML Request JS
var xhr = new XMLHttpRequest();
console.log(xhr);
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4) return; {
console.log(JSON.parse(xhr.responseText));
}
};
xhr.open("GET", "/api/storefront/orders/" + buildOrderID() + "");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("Cache-Control", "no-cache");
xhr.send();
Fetch Request JS
fetch("/api/storefront/orders/" + buildOrderID() + "").then(function (response) {
// The API call was successful!
return response.json();
}).then(function (data) {
// This is the JSON from our response
console.log(data);
}).catch(function (err) {
// There was an error
console.warn('Something went wrong.', err);
});
Related
I am learning to use XMLHttpRequest object.
With help from the web, I have written a simple html file to retrieve data and display in the page.
<!DOCTYPE html>
<html>
<head>
<title>XMLHttpRequest</title>
</head>
<body>
<script>
var request = new XMLHttpRequest();
request.onload = function(){
if(this.status !== 200){
console.log("Error: " + this.status);
}
else{
document.getElementById("stat").innerHTML = this.status;
document.getElementById("size").innerHTML = this.response.length;
document.getElementById("data").innerHTML = JSON.parse(this.response);
}
}
request.open('GET','https://hplussport.com/api/products');
request.send();
</script>
<div>
Response Data<br/>
Status: <span id="stat">Loading...</span><br/>
Size : <span id="size">Loading...</span> bytes<br/>
Data : <span id="data">Loading...</span>
</div>
</body>
</html>
The request works fine if the URL is correct but if there are any errors in the URL, nothing happens. I understand that if there is no response, then this.response will be empty but I thought that this.status would still have a value and, therefore, the console would report "Error" + this.status however, it doesn't. It does trigger the error report in the console if I change request.onload to request.onreadystatechange but I get the error reported twice.
So my question is, why does request.onload not work and request.onreadystatechange does work (twice) and which one should I use? I feel like I should use request.onload.
onload is triggerd once when the request completes and is a 2xx status. for error codes you would have to add the onerror = callback
onreadystatechange will be called 4 times no mather what status code you get
when it opens a request,
when the full request header + body have been sent
when the response headers returns (then you know the response status and the response headers)
and finally when the hole response body is downloaded
XMLHttpRequest is quite old and have its bugs/quirks that have been fixed in modern browser but there is a newer api called fetch it is a bit more superior cuz you can also stream large data with ReadableStreams + it works well in web workers, Deno and NodeJS too (unlike XMLHttpRequest)
I recommend to learn/use fetch instead
then your code would looks something like this:
var res = await fetch('https://hplussport.com/api/products')
if (response.ok) {
// status was 2xx
const json = await res.text()
document.getElementById("stat").innerHTML = res.status;
document.getElementById("size").innerHTML = new Blob([text]).size;
document.getElementById("data").innerHTML = json;
} else {
// status was not 2xx
console.log("Error: " + res.status);
}
I'm creating a website to progress in javascript and I have a little problem, every ways I try, my browser doesn't want to load my json file.
I tried many codes i found on internet but none of them work (or I don't know how to make them work). Finally i fond this one which is quite easy to understand but yhis one too doesn't work and always return an error message.
function loadJSON(path,success, error)
{
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function()
{
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 1) {
if (success)
success(JSON.parse(xhr.responseText));
} else {
if (error)
error(xhr);
}
}
};
xhr.open("GET", path , true);
xhr.send();
}
function test()
{
loadJSON('test.json', function(data) { console.log(data); }, function(xhr) { console.error(xhr); });
}
I run the test function but everytimes, the console return me an error. Someone have an idea to solve my problem ?
status is the HTTP response code.
200 means the request has been successful. The status will most likely never be 1.
Here is a list of HTTP codes
As a solution, I suggest using the fetch API, which is the modern way to query files.
Here are some examples on how to use it
If you really want to use AJAX, use this :
var request = new XMLHttpRequest();
request.open('GET', '/my/url', true);
request.onload = function() {
if (this.status >= 200 && this.status < 400) {
// Success!
var resp = this.response;
} else {
// We reached our target server, but it returned an error
}
};
request.onerror = function() {
// There was a connection error of some sort
};
request.send();
Source : You Might Not Need jQuery
Hi there i am stuck and somehow don't find the solution. It seems simple but, well ok. Here it goes. I have a mobile service in Azure and i want to reach that one with javascript. How do i get around the 401 Unauthorized? I tried with the documentation supplied from MS but no luck. This is what i got so far (adding the key to the url is not working of course) what can i add to get it to work?
var client = new WindowsAzure.MobileServiceClient(
"https://cdshop.azure-mobile.net/",
"vGpqzyApJXXXXXXXXblQCWne73"
);
var getJSON = function (url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('get', url, true);
xhr.responseType = 'json';
xhr.onload = function () {
var status = xhr.status;
if (status == 200) {
callback(null, xhr.response);
} else {
callback(status);
}
};
xhr.send();
};
$(function () {
$('#clickme').click(function () {
getJSON('http://cdshop.azure-mobile.net/api/cds/total?key=vGpqzyApJXXXXXXXXblQCWne73', function (err, data) {
if (err != null) {
alert('Something went wrong: ' + err);
} else {
alert('Your Json result is: ' + data.result);
result.innerText = data.result;
}
});
});
});
If you are creating your own HTTP requests, you need to set a request header called X-ZUMO-APPLICATION with your Application Key, e.g. "vGpqzyApJXXXXXXXXblQCWne73", for tables and APIs that are set to "application" or "users". (Assuming you are still using Mobile Services; the newer App Service does not use this X-ZUMO-APPLICATION header.) Tables and APIs set for "users" also need an X-ZUMO-AUTH request header with the user's authentication token.
Alternatively, you can use the MobileServiceClient you created in the first line, and it will do this for you. This page has examples for calling APIs and tables. For your example:
client.invokeApi("cds", {
body: null,
method: "get"
}).done(function (data) {
alert('Your Json result is: ' + data.result);
result.innerText = data.result;
}, function(error) {
alert('Something went wrong: ' + error);
});
I am running a nodejs server to run my website, and I want the backend server to make a call to an api on an external server. I tried the following, basic and straightforward method:
router.post('/calculate', function (req, res) {
var data = /*some json object*/
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", "some.server/pricing");
xmlhttp.setRequestHeader("Content-Type", "application/json");
xmlhttp.send(JSON.stringify(data));
xmlhttp.onreadystatechange = function() {
if(xmlhttp.status == 200)
{
var str = xmlhttp.responseText.toString().trim()
dd = JSON.parse(str);
res.send(dd);
//res.end();
}
};
});
When I run this I get:
_http_outgoing.js:346
throw new Error('Can\'t set headers after they are sent.');
^
Error: Can't set headers after they are sent.
The issue seems to be in res.send(dd);
EDIT:
Upon further investigation, it seems like xmlhttp.onreadystatechange happens twice with status 200, and res.send is called twice. I created a temporary hack to fix this using a boolean flag, what is the rpoper nodejs way to fix this?
What is the most straightforward way of making such a call in nodejs? I want this done on the server side. I am not using any libraries like express. Thanks
Easy do it with request package
var request = require('request');
request({
url: 'some.server/pricing',
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
form: data
}, function (err, res, body) {
if (err) res.send(err)
else res.send(body)
});
After a lot more investigation, I found out that res.send was being called twice. The reason this was happening was because the xmlhttp object changes its state several times:
http://www.w3schools.com/ajax/ajax_xmlhttprequest_onreadystatechange.asp
I fixed the code to:
if (xhttp.readyState == 4 && xhttp.status == 200)
Now everything works properly.
I have the following headers set on the server
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT");
response.addHeader("Access-Control-Allow-Headers","X-Custom-Header");
And i want to use the POST method to access a web service and send data to it but the problem is my setting up with the server is causing problems
I used the following method
function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// XHR for Chrome/Safari/Firefox.
xhr.open(method, url, true);
}
else if (typeof XDomainRequest != "undefined") {
// XDomainRequest for IE.
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// CORS not supported.
xhr = null;
}
return xhr;
}
and based on this object
url = "http://myurl.do";
var xhr = createCORSRequest('POST', url);
if (!xhr) {
alert('CORS not supported');
return;
}
var params = "name=pari123&action=initaction&gameId=slotreel3";
xhr.setRequestHeader('Content-Type', 'application/text/plain');
if(xhr.readyState == 4 && xhr.status == 200)
{
alert('Tested OK')
xhr.send(params);
}
else
{
alert('status not 200 or xhr is not ready');
}
// Response handlers.
xhr.onload = function() {
var text = xhr.responseText;
alert('Response from CORS request to ' + url + ': ' + text);
};
xhr.onerror = function() {
alert('Woops, there was an error making the request.');
};
But always it alerts a message saying 'status not 200 or xhr is not ready' i am not able to proceed any one if you know please kindly help!
when i print the xhr.readyState its printing a value of 1
if(xhr.readyState == 4 && xhr.status == 200)
This check must be placed in the onreadystatechange event handler. You obviously cannot have a 200 status code or a "finished" request before actually sending it.
What you wanted is probably this:
xhr.onreadystatechange = function() {
if(xhr.readyState == 4 && xhr.status == 200) {
alert('Tested OK');
var text = xhr.responseText;
alert('Response from CORS request to ' + url + ': ' + text);
}
};
xhr.send(params);
If you want an else case to check for errors remember that you still need to check for xhr.readyState == 4. You don't want your error-handling code to run for other readyStates.
There is no need for the onload event - when you get readyState == 4 you know the request has finished.
There can be several issues here.
I observed that different browsers implement CORS differently. My experience is based on Firefox and Google Chrome. For example, I had to add a special header on server side, so that Firefox would make the preflight (OPTIONS) request and the actual request (GET,PUT etc.) using one connection as Google Chrome does it. You would have to add on the server side:
response.addHeader("Keep-Alive", "timeout=2, max=100");
response.addHeader("Connection", "Keep-Alive");
I also noticed that some browsers do not like the wildcard ("*") in the CORS headers. A workaround for the line
response.addHeader("Access-Control-Allow-Origin", "*");
would be to return the origin of the request and not a wildcard.
However, there could be also other problems and we would need more details. For example, does the request work when the server is hosted on the same domain (i.e. the problem might not be related to CORS). What server are you using?
xhr.send(); needs to be just after the call to xhr.open(); does it not? Status 1 means the request has not been sent yet, it'll never get to status 4 unless you actually send the request..