I have an API that returns 302 status code with the destination location.
But when i am calling this API from my angular code, the browser is not redirecting to destination URL. Rather it's calling that destination URL(which is an HTML page) with XHR and giving error like:
error: SyntaxError: Unexpected token < in JSON at position 0 at Object.parse () at XMLHttpRequest.onLoad
text: "\n
Basically it tried parse the HTML response as JSON and failed.
So how can I make browser to redirect to destination URL rather than calling it as XHR.
Browser won't jump to the Location which is returned by XHR 302 response's header. If you want to let the browser redirect, you should make it by your own.
Here is the code:
const url = 'http://your-api.com'
const xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
// This means our request undergoes a redirection
if (xhr.responseURL !== url) {
window.location = xhr.responseURL
}
else {
// Do something else, like JSON.parse(xhr.responseText)
}
}
}
xhr.open('GET', url)
xhr.send()
Related
I am trying to access YouTube v3 API and getting user info using access token. I am getting full JSON in response with all details with i want but this error also come with that.
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.open('GET',
'https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true&' +
'access_token=' + access_token);
xhr.onreadystatechange = function (e) {
var channel = xhr.response.items[0]; **// This is the error line**
document.getElementById('token').value = user.Zi.access_token;
};
xhr.send(null);
console log
Uncaught TypeError: Cannot read property 'items' of null
at XMLHttpRequest.LoadData.xhr.onreadystatechange
LoadData.xhr.onreadystatechange # main.js:93
XMLHttpRequest.send (async)
LoadData # main.js:101
setSigninStatus # main.js:65
updateSigninStatus # main.js:114
(anonymous) # cb=gapi.loaded_0:267
c.port1.onmessage # cb=gapi.loaded_0:153
You're not waiting for the response to be complete, and you're not checking for success. You need to check readyState === 4 to know whether the response is complete, and status === 200 to know if the request was successful:
var xhr = new XMLHttpRequest();
xhr.responseType = 'json';
xhr.open('GET',
'https://www.googleapis.com/youtube/v3/channels?part=snippet&mine=true&' +
'access_token=' + access_token);
xhr.onreadystatechange = function (e) {
if (xhr.readyState === 4) {
// Request is complete -- did it work?
if (xhr.status === 200) {
// Success
var channel = xhr.response.items[0];
document.getElementById('token').value = user.Zi.access_token;
} else {
// Failure, handle/display error
}
}
};
xhr.send(null);
Side note: You don't appear to be using channel after retrieving it. Instead, you're using some user variable that the code closes over. I assume your real code will use channel. :-)
Side note 2: In modern environments, you might use fetch instead of XMLHttpRequest. But if you do, beware of the footgun in the API that I describe on my blog (TL;DR - be sure to check ok before calling any of the body load methods).
const Http = new XMLHttpRequest();
const url='https://www.instagram.com/nasa/?__a=1';
Http.open("GET", url);
Http.send();
Http.onreadystatechange = (e) => {
console.log(Http.responseText);
var instaData = JSON.parse(Http.responseText);
console.log(instaData);
}
I'm trying to get a JSON object from an Instagram page so that I can extract some basic user data. The above code gets a string from Instagram that looks like a properly formatted JSON object, but when I try to use JSON.parse on it I get the error message "JSON.parse: unexpected end of data at line 1 column 1 of the JSON data".
I can't include the full output of Http.responseText because it's too long at 8,000+ characters, but it starts like this:
{"logging_page_id":"profilePage_528817151","show_suggested_profiles":true,"show_follow_dialog":false,"graphql":{"user":{"biography":"Explore the universe and discover our home planet. \ud83c\udf0d\ud83d\ude80\n\u2063\nUncover more info about our images:","blocked_by_viewer":false,"country_block":false,"external_url":"https://www.nasa.gov/instagram","external_url_linkshimmed":"https://l.instagram.com/?u=https%3A%2F%2Fwww.nasa.gov%2Finstagram&e=ATOO8om3o0ed_qw2Ih3Jp_aAPc11qkGuNDxhDV6EOYhKuEK5AGi9-L_yWuJiBASMANV4FrWW","edge_followed_by":{"count":53124504},"followed_by_viewer":false,"edge_follow":
You are trying to do a cross origin request without setting the Origin header. If a given api endpoint supports CORS, then when the Origin header is passed in the request it will reply with the "access-control-allow-origin" header.
I confirmed that the instagram url in your question does support CORS.
The following code using the fetch api works.
fetch('https://www.instagram.com/nasa/?__a=1', { mode: 'cors' })
.then((resp) => resp.json())
.then((ip) => {
console.log(ip);
});
You should read through the MDN CORS info https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS.
Here's also a fixed version of your original code:
const Http = new XMLHttpRequest();
const url = 'https://www.instagram.com/nasa/?__a=1';
Http.open("GET", url);
Http.setRequestHeader('Origin', 'http://local.geuis.com:2000');
Http.send();
Http.onreadystatechange = (e) => {
if (Http.readyState === XMLHttpRequest.DONE && Http.status === 200) {
console.log(Http.responseText);
}
}
I have a domain A "xbo.dev" and a sub domain B "blog.xbo.dev".
For example, on B domain, I would like to make an Ajax request to a domain A function.
I'm trying this with FOSUserBundle authentication. What I do :
var xhr = new XMLHttpRequest();
if ('withCredentials' in xhr) {
xhr.open('POST', 'http://xbo.dev/ajax/check_login_ajax', true);
// I am using hard coding for the URL because with Routing.generate I would have this URL : http://blog.xbo.dev/ajax/check_login_ajax
// which is not good because the request is on a different domain
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 400) {
console.log(xhr);
console.log('ok');
} else {
console.log('ko');
}
}
};
xhr.send(encodeURI('_username=' + $('#co_'+varName+'username').val() + '&_password=' + $('#co_'+varName+'password').val() + '&_remember_me=' + false + '&_csrf_token=' + $('#co__csrf_token').val()));
I have a "ok" displayed by my request but nothing special is happening (I should have something like "Bad credentials" or "success" (or others), returned by FOSUserBundle check_login_ajax function, but no one of those is displayed...)
How can I do ?
EDIT 1 : Here is the result I have each time, either the login / password are correct or not
And with a normal $.ajax, I have this :
You need to implement something to relax the same-origin policy such as CORS.
As to your in-code note about hard-coding vs using the router to generate URLs, Symfony's router supports hostnames.
I'm using Topaz Signature pads & implementing their new AJAX library. I want to display a warning on the page if the page if the driver/service is not installed/running. To do this, the script makes a get request to a domain which redirects to localhost via the hosts file.
If the service is running, I get the status of the signature pad & everything is fine. If however, the service is not installed or not running, I just get NS_ERROR_FAILURE and the script halts, even if I'm within try{code}catch(err){errorcode}
try {
console.log('connect: ' + TabletConnectQuery());
}
catch(err){console.log('Caught ' + err);}
My console just shows:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://tablet.sigwebtablet.com:47290/SigWeb/TabletState. (Reason: CORS request failed).
Line 0
NS_ERROR_FAILURE:
https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js line 2 > eval
Line 151
This is particularly troublesome as it occurs during a page transition & stops the animation dead.
I ended up getting it to work by modifying the SigWebTablet.js library topaz provided.
Changed
function SigWebGetProperty(prop) {
var xhr = SigWebcreateXHR();
if (xhr) {
xhr.open("GET", baseUri + prop, false );
xhr.send(null);
if (xhr.readyState == 4 && xhr.status == 200) {
return xhr.responseText;
}
}
return "";
}
To:
function SigWebGetProperty(prop) {
var xhr = SigWebcreateXHR();
if (xhr) {
xhr.open("GET", baseUri + prop, false );
try{
xhr.send(null);
}
catch(err){
return "";
}
if (xhr.readyState == 4 && xhr.status == 200) {
return xhr.responseText;
}
}
return "";
}
I am developing an extenion which makes an ajax request to a web server like this
var xhr = new XMLHttpRequest();
xhr.open(method, url, true);
xhr.setRequestHeader("Content-Type","application/json");
xhr.send(JSON.stringify(data));
xhr.onreadystatechange = function()
{
if(xhr.readyState == 4 && xhr.status == 204)
{
//debugger;
alert("Logged in");
flag = 1;
_callBack(xhr, xhr.readyState);
}
}
And here i am able to logged in with status = 204 and now once i logged in i am trying to go for different directory for example www.example.com/index/enter with another ajax request in same extension but could not able to do so.
Are you sure you're expecting the same HTTP response code? It's very likely that the server you're making requests to is sending a different response for a different request URL.
204 No Reponse = there is no response data
200 OK = there is data