I am making a cross browser jsonp call in which my backend to which i am sending some values is made using django and getting some after callback to my front end which is in php . The problem is its giving Uncaught SyntaxError: Unexpected token : error The data is being send from the django and i have checked that. i am using the code below to make jsonp calls
$(document).on('click', '.miloginme', function(event) {
var username = $('#username').val();
var password = $('#password').val();
var token = $('#token').val();
var dataString="uid="+username+"&token="+token;
$.ajax({
type: 'POST',
url: "http://localhost:8000/b/authenticate/",
crossDomain: true,
data: dataString,
async: false,
dataType: 'jsonp',
success: function(data) {
alert(data);
}
});
});
the values in callback that i am getting is in format
{"token": "KAMWMS151UWPR4Q", "authenticate": "1", "userid": "brad", "fname": "rahul", "booster_number": "1"}
tldr; The server is not sending back JSONP.
Value reported in the post is JSON (and it is valid JSON) - it is not JSONP. If it were to be treated as JSONP (i.e. evaluated by a <script>) then it would be a syntax error because it is not a valid JavaScript program.
Try this in a JavaScript console:
{"token": "KAMWMS151UWPR4Q", "authenticate": "1", "userid": "brad", "fname": "rahul", "booster_number": "1"}
Error look familiar? (Different browses can return different error messages: Chrome -> "Unexpected token :", FireFox -> "invalid label", IE9 -> "Expected ';'".)
A valid JSONP result would look similar to:
theCallback({"token": "KAMWMS151UWPR4Q", "authenticate": "1", "userid": "brad", "fname": "rahul", "booster_number": "1"})
(The name of theCallback is taken from the jsonp variable passed to the server and the client - e.g. jQuery - creates this function before the injecting <script> element is created so that the function can be invoked using the above syntax.)
Valid JSONP works because the "JSON" data is then run in an expression context (in which it is treated as a valid JavaScript Object Literal), not a statement context (where it is treated as a label and then "some junk" leading to a syntax error).
Common approaches to return JSONP from Django utilize View Decorators:
Django JSONP Decorator
Returning JSON/JSONP from a Django view with a little decorator help
jsonp_decorator.py
Related
Currently in my web app project, I need to parse the content of a web page, and after some searching, I found that Mercury Web Parser API is quite suitable for me.
And I have some experience with such kind of third party APIs, generally speaking I can get my desired result.
But for this API, I can't find documentation about the API usage on the official website.
Based on the my study, it provide two methods:
first is cURL as following:
curl -H "x-api-key: myapikey" "https://mercury.postlight.com/parser?url=https://trackchanges.postlight.com/building-awesome-cms-f034344d8ed"
the myapikey is the API key I get from the website. Then I can get the result in JSON format, which is the main content of the web page specified by the url parameter. It works well for me, I mean the cURL method.
And on the website, it said that the second method is HTTP call, which is just what I need:
GET https://mercury.postlight.com/parser?url=https://trackchanges.postlight.com/building-awesome-cms-f034344d8ed
Content-Type: application/json
x-api-key: myapikey
So based on my understanding, I use jquery AJAX method to do this as following:
var newurl = "https://mercury.postlight.com/parser?url=http://www.businessinsider.com/joel-spolsky-stack-exchange-interview-2016-12&x-api-key=myapikey"
$.ajax({
url: newurl,
dataType: "jsonp",
success: function(data){
console.log(data.title);
}
})
here I made JSONP request because of the Cross origin issue.
But now I face 401 error message (401 Unauthorized. The request has not been applied because it lacks valid authentication credentials for the target resource)
For now my guess is that the apikey is not correctly passed to server. So based on the cURL's successful call, can I get the correct format for AJAX call?
Update:
Based on the following answers ,I tried to set the request header as following:
$.ajax({
url: newurl,
dataType: "jsonp",
beforeSend: function(xhr){
console.log(apiKey);
xhr.setRequestHeader('x-api-key', apiKey);
},
/*
headers: {
"x-api-key": "M1USTPmJMiRjtbjFNkNap9Z8M5XBb1aEQVXoxS5I",
"contentType": 'application/json'
},
*/
success: function(data){
console.log("debugging")
console.log(data.title);
},
error: function (error) {
console.log(error)
}
})
I tried both beforeSend and headers. But still can't work and get the following trackback error message:
send # jquery.js:8698
ajax # jquery.js:8166
addNewArticle # topcontroller.js:18
fn # VM783:4
e # angular.js:281
$eval # angular.js:147
$apply # angular.js:147
(anonymous) # angular.js:281
dispatch # jquery.js:4435
elemData.handle # jquery.js:4121
And for the last send function, still 401 error.
But the ajax error handling part shows that the readyState:4 and status: 404 result. So what's going here.
For your question, the curl request is sending a header which you have attached as part of the query string in your $.ajax request.
Try the following instead (using beforeSend + xhr) :
// broke this string down so you don't have to scroll
var newurl = "https://mercury.postlight.com/parser?" +
"url=http://www.businessinsider.com/" +
"joel-spolsky-stack-exchange-interview-2016-12";
// set your api key
var apiKey = "<your api key>";
$.ajax({
url: newurl,
dataType: "json",
beforeSend: function(xhr){xhr.setRequestHeader('x-api-key', apiKey);},
success: function(data){
console.log(data.title);
}
})
I am trying to retrieve a JSON from this URL
http://www.iheartquotes.com/api/v1/random?format=json
via jQuery. I know the solution is JSONP, but since I have no control over the response text of the service or to wrap it in my own callback function, my aim is to somehow retrieve the response of the above URL using client-end scripts.
I have tried almost all the methods suggested from several answers from StackOverflow.
These are the code blocks I have tried and the response's I've got.
1 . A direct call which returned the expected Access-Control-Allow-Origin error
$.getJSON("http://www.iheartquotes.com/api/v1/random?format=json",
function(data) {
alert(data);
});
Response:
XMLHttpRequest cannot load
=1376682146029">http://www.iheartquotes.com/api/v1/random?format=json&=1376682146029.
Origin http://stackoverflow.com is not allowed by
Access-Control-Allow-Origin.
2 . The above code with the callback parameter added:
$.getJSON("http://www.iheartquotes.com/api/v1/random?format=json&callback=?",
function(data) {
alert(data);
});
Response:
Uncaught SyntaxError: Unexpected token :
Please note that when I click on the error, it takes me to the expected JSON response.
{"json_class":"Fortune","tags":["simpsons_homer"],"quote":"Holy Moly! The bastard's rich!\n\n\t\t-- Homer Simpson\n\t\t Oh Brother, Where Art Thou?","link":"http://iheartquotes.com/fortune/show/5501","source":"simpsons_homer"}
This is also expected as there is no callback function defined in the response.
3 . Through jQuery's Ajax method
$.ajax({
type: "GET",
dataType: "jsonp",
url: "http://www.iheartquotes.com/api/v1/random?format=json",
success: function(data){
alert(data);
},
});
Response:
Uncaught SyntaxError: Unexpected token :
Adding the callback parameter to the above function doesn't change the response.
Any help or pointers from the experts to retrieve the JSON from the URL? I am testing this from the Chrome Dev Tools. I know I could call the service from the server-end code and then send it across to the client-end. But I want to see if this can be done through jQuery alone from the client-end.
EDIT:
Based on Kevin B's comment:
Got the expected output via YQL using jQuery's Ajax. But my question remains the same. Is there a native way to do it via jQuery as YQL is still a dependency?
// Using YQL and JSONP
$.ajax({
url: "http://query.yahooapis.com/v1/public/yql",
// the name of the callback parameter, as specified by the YQL service
jsonp: "callback",
// tell jQuery we're expecting JSONP
dataType: "jsonp",
// tell YQL what we want and that we want JSON
data: {
q: "select * from json where url=\"http://www.iheartquotes.com/api/v1/random?format=json\"",
format: "json"
},
// work with the response
success: function( response ) {
console.log( response.query.results.json ); // server response
}
});
This gives the expected response.
This won't work in all browsers, but depending on which version of JQuery you're using try:
$.support.cors = true;
Obviously this also depends on the headers of the server response.
Any idea why this does not work in IE9 but does in Chrome and Firefox?
$.get("http://nominatim.openstreetmap.org/search", { format: "json", q: val, polygon: 0, addressdetails: 1 })
.done(function(results) {
if (!results) return;
// do something
});
I know IE8 wont support it but i thought 9 would?
Update:
New code
$.ajax({
type: 'GET',
url: "http://nominatim.openstreetmap.org/reverse",
data: { format: "json", lat: lat, lon: lng, zoom: 18, addressdetails: 1 },
error: function(xhr, status, error) {
myTable.fnUpdate("Not supported by browser", aPos[0], 4);
},
success: function(data){
myTable.fnUpdate(data.display_name, aPos[0], 4);
}
});
At least with this i can show "Not supported by browser" rather than nothing happening, are there no tricks to make it work in IE9?
Update 2:
This seems to work in FF, Chrome and IE9.
http://jsfiddle.net/BXhkm/4/
But when i add the same code to my app the first request is successfull, then i get Error: data was not called.
To solve cross domain issues, you need to read the documentations of the Server API and the one of jQuery.
If the browser/framework does not support cross domain requests via GET or POST you need to fallback to JSONP requests.
Wiki docs of Openstreetmap Nominatim:
json_callback=<string> Wrap json output in a callback function (JSONP)
This tells you that the parameter that defines the callback function is json_callback
Now you look at the docs of your framework:
jQuery.getJSON
section JSONP
If the URL includes the string "callback=?" (or similar, as defined by the server-side API), the request is treated as JSONP instead. See the discussion of the jsonp data type in $.ajax() for more details.
This tells you if you include a paramter in your request url and that has the value ?. This ? is replaced by the callback method for the JSONP request.
Out of this two informations you create this query:
$.getJSON("http://nominatim.openstreetmap.org/reverse?json_callback=?",
{ format: "json", lat: lat, lon: lng, zoom: 18, addressdetails: 1 },
function(data) {
console.log("success");
});
Instead of getJSON you can for sure use ajax the important part is that you do a jsonp request.
EDIT
The first ? marks the beginning of the parameter list, the second ? is the placeholder for the jsonp callback.
http://nominatim.openstreetmap.org/reverse?json_callback=?
I upgraded my page from using jquery 1.4.4 to jquery 1.9.1 and suddenly my ajax calls stopped working. If i revert to jquery 1.4.4 it works again. I am getting below error.
No conversion from text to string
Below is my code
$.ajax({ url: "/Reporting/RunQuery",
type: "Post",
data: { prm_Query: qrytxt }, dataType: "string",
error: function (XMLHttpRequest, status, error) {
debugger;
alert("The following error occured while adding data: " + error);
},
success: function (data) {
debugger;
$('#divQuerytextarea').html('').append(data);
}
});
My call to /Reporting/RunQuery succeeds and it has valid return string in the RunQuery method. Then it falls into error: of ajax call with 'No conversion from text to string' error.
Not finding much in google for this. Any help is appreciated.
I agree with Kevin. I was having the same problem just because I've put :
dataType: JSON
instead of :
dataType: "json"
after what everything worked fine.
Be aware that this "dataType" property commes from the HTTP head where there is the MIME type wich is the type of the resource called by the HTTP request. So there is no "string" type. You should use "text" instead (if you want a string, of course).
Below is a cross-domain call I'm trying to make via an Ajax call. The web service we're using only returns XML, so I cannot use jsonp as a dataType. As I have it written below, I receive the following error in Chrome's debugger:
Uncaught ReferenceError: Request is not defined
Here is the code:
function GetProgramDetails() {
var URL = "http://quahildy01/xRMDRMA02/xrmservices/2011/OrganizationData.svc/AccountSet?$select=AccountId,Name,neu_UniqueId&$filter=startswith(Name,\'" + $('.searchbox').val() + "\')";
var sourceDomain = Request.Headers["Origin"];
var request = $.ajax({
type: 'POST',
beforeSend: function(request){
request.setRequestHeader("Access-Control-Allow-Origin", sourceDomain)
},
url: URL,
contentType: "application/x-www-form-urlencoded",
crossDomain: true,
dataType: XMLHttpRequest,
success: function (data) {
console.log(data);
alert(data);
},
error: function (data) {
console.log(data);
alert("Unable to process your resquest at this time.");
}
});
}
EDIT
I've tried the following versions of this code and haven't seen anything different in the error message. This is being used in an enterprise environment, so is it possible that, due to security features on the server, it is not possible for this to work? I'm brand new to Ajax, so I don't know if this is something that works 100% of the time or just in a majority of settings.
beforeSend: function (request) {
request.setRequestHeader("Access-Control-Allow-Origin: *")
},
beforeSend: function (request) {
request.setRequestHeader("Access-Control-Allow-Origin: ", "http://localhost:55152")
},
beforeSend: function (request) {
request.setRequestHeader("Access-Control-Allow-Origin", "http://localhost:55152")
},
beforeSend: function (request) {
var sourceDomain = request.Headers["http://localhost:55152"];
request.setRequestHeader("Access-Control-Allow-Origin: ", sourceDomain)
},
beforeSend: function (request) {
var sourceDomain = location.protocol + '//' + location.host;
request.setRequestHeader("Access-Control-Allow-Origin: ", sourceDomain)
},
This is your problem: var sourceDomain = Request.Headers["Origin"]; You have not defined Request with a capital R.
The meat of your problem is going to be in the cross-domain request. This is possible and you're on the right track but Access-Control-Allow-Origin is something that's set on the server as a response header, not something that's sent by the client through XHR as a request header. See https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS#Access-Control-Allow-Origin
See the HTML5 Boilerplate .htaccess as an example of how to set this up on Apache https://github.com/h5bp/html5-boilerplate/blob/master/.htaccess and note the browser limitations https://www.bionicspirit.com/blog/2011/03/24/cross-domain-requests.html - notably that this doesn't work in IE7 and that IE doesn't support wildcards *.
Trying to mimic jsonp (returning executable JavaScript code from the server) may be possible with some clever coding but this would be more difficult - Using JSONP when returning XML
Also, if the data is sensitive then you might not want to do any sort of cross-domain request without a private key scheme since I'm not sure if the origin request header can be spoofed. The alternative would be to set up a connection for your websites to share data on the back-end rather than the front-end.
Also, JavaScript function names are not capitalized unless they are constructors.
beforeSend: function(request){
var sourceDomain = request.Headers["Origin"];
request.setRequestHeader("Access-Control-Allow-Origin", sourceDomain)
},
You were attempting to access the request before it was created, thus throwing the undefined error. The request is the jqXHR object which is passed to the beforeSend() callback function.