I have a webservice(REST) running on localhost:8080, to call the webservice I use this jquery code:
jQuery.ajax({
type: "POST",
url: "http://localhost:8080/user/register",
data: '{"name": "' + name + '","email": "' + email + '","password": "' + password + '"}',
beforeSend: function(x) {
if(x && x.overrideMimeType) {
x.overrideMimeType(jsonMimeType);
}
},
dataType:"jsonp",
Accept : "application/json",
contentType: "application/json",
success: registerUser_success_callback,
error: registerUser_error_callback
});
When I try to call this javascript from the same domain(i.e. localhost:8080), it work just like a charm!. Here is the screen shot of the same:
But when I try to access the same from a different domain(i.e localhost:80), it fails, and surprisingly instead of a POST, it sends out a GET and I also get a log in my server's log file, saying that the GET method not supported for REST resource. Here is the screen of the same:
From what I have read on internet(especially here, great article!), cross domain request should first send out an OPTIONS request(which is cached for later usage.) What is going wrong in my case?
I have tried calling the rest service with same parameters using FireFox's plugin RESTClient, I was able call the rest service(POST method) successfully, so this mostly is the issue with ajax part.
Help me resolve this cors hell! and do lemme know if I need to share any more details on this.
PS: After #A. Wolff Suggested, I changed the data tyoe from jsonp to json, now my browser sends out OPTIONS, but after that it doesn't send the actual POST request!!!
Well, some more digging and I found the solution to this!
After the change A. Wolff suggested, browser was sending out an OPTIONS request and was receiving a 200 response, but after that actual POST request was not being sent to the server.
Problem was, if you send any specific headers, "Content-Type" in my case, server has to add that header in "Access-Control-Allow-Headers" field of the response(response of OPTIONS request). I changed my server side code to populate that field in the response header, and VOILA!
Hope this will be helpful to others, too!
Happy Coding.
Related
I am trying to write a simple script to obtain JSON data but the target requires login information in the actual URL like so:
http://login:password#URL/theapi
It appears that when using either getJSON or straight ajax the login details get skipped though even when passed on. I get an 401 error in developer tools in Chrome where it's interesting that the link in the error, when clicked, will actually go through and get he JSON data in to the browser
Is there a way around this?
Is there a way around this?
Yes, while making the AJAX call, don't attach login:password in the url. Instead, add Authorization header with Base64 encoded value of login:password. This is how we can do using JQuery:
$.ajax({
type: "GET",
url: "https://domain.tld",
dataType: "json",
beforeSend: function(xhr) {
xhr.setRequestHeader ("Authorization", "Basic " + btoa(login + ":" + password));
}
});
I apologize if this question has already been answered.
I am trying to retrieve data from a REST web service that exposes a JSON interface using jQuery .ajax call.
When I call the service using the URL, the jQuery call fails although I get a HTTP status code 200 OK.
When I copy the response into a file on the filesystem and retrieve this, the same call works.
Both the file I am accessing and the web service I am calling are on the same machine.
Some notes on the url used in the code below:
Using:
url: "http://localhost:9090/app/user/861",
the call fails, goes into .fail on all browsers.
The URL itself returns the json on all browsers:
{
"userid": 861,
"employeeno": "123",
"jobdesc": "Developer",
"firstname": "Jasper",
"lastname": "Fitussi"
}
when using "test.json" in the local filesystem following is the behavior:
url: "ajax/test.json",
On Firefox, the call executes, goes into .done and displays the result on page.
On Chrome, the call fails with status 404 and the following message -
"No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access."
I tried different combinations changing dataType:"jsonp", adding a ?callback=? to the end of the URL, and enclosing the data in the test.json with a '(' and a ')' without luck.
Please understand I am new to UI programming, javascript and jQuery.
Please help with what I am doing wrong. Here's the javascript:
<script src="http://code.jquery.com/jquery-1.10.2.js" type="text/javascript">
</script>
<script type="text/javascript">
$(document).ready(function () {
$.ajax({
type: "GET",
url:"ajax/test.json",
// the following commented call fails, goes into .fail
// url:"http://localhost:9090/app/user/861",
contentType: "application/json",
accepts: "application/json",
dataType: "json"
})
.done(function(data) {
alert("Success");
console.log(data);
var items = [];
$.each( data, function( key, val ) {
items.push( "<li id='" + key + "'>" + val + "</li>");
});
$( "<ul/>", {
"class": "my-new-list",
html: items.join( "" )
}).appendTo( "body" );
})
.fail(function(data) {
console.log(data);
alert("Failed");
})
.always(function() {
alert("In Always");
});
});
</script>
The following is the output when I paste the url into the browser (also the contents of ajax/test.json):
{
"userid": 861,
"employeeno": "123",
"jobdesc": "Developer",
"firstname": "Jasper",
"lastname": "Fitussi"
}
Your problem is not about UI programming, it's about the security model of modern browsers :p
Access-Control-Allow-Origin errors occurs when you call a webservice (ie: load a JSON file) from a domain that is different from the one hosting your HTML page.
In your case, you are opening the html file from your hard drive (file:///) and calling a webservice on localhost.
This is a security feature in all modern browsers that forbid getting data from a foreign webservice without the webservice owners authorizing you (or everyone, wildcards are allowed) to call it.
I recommend reading the following guide from MDN, so that you understand WHY you are having this problem.
It will then be easy to resolve
https://developer.mozilla.org/en/docs/HTTP/Access_control_CORS
If you control the source code of the webservice, or the webserver hosting it, you need to add Access-Control-Allow-Origin HTTP headers.
Do you make your ajax call using Apache on wamp, lamp, xampp or mamp or not? I think you work directly using some files lets say on your desktop and not from the www file of wamp. If the browser sends a correct url then the backend responds great, your frontend code seems fine so i think chrome complains about your not using localhost. Am i right? Whats your local development setup?
If it's a local file on the client-side, use file:/// to prefix the URL:
url: 'file:///ajax/test.json'
The third / in file:/// indicates:
As a special case, can be the string "localhost" or the empty
string; this is interpreted as `the machine from which the URL is
being interpreted'.
3.10
Reference here
Download a tool called fiddler, from http://fiddler2.com/ great way to debug web requests and to see why they are failing.
This will help you narrow down the issue you are experiencing and we can help you further because currently its all guess work.
I had the same issue, all worked fine in I.E and FireFox, a had one ajax call to a rest service using jsonp and it worked fine in chrome, however when I tried to load a file using jsonp I got the cross domain error. In short i had to add "file:" to my file path in the url
$.ajax({
type : 'GET',
url : 'file:jsondata/rain_acc_data.json',
dataType : 'jsonp',
jsonpCallback : "jsoncallback",
success : function(data) {
aler('ok');
},
error : function(jqXHR, status) {
alert("Failed to load list" + status + jqXHR);
}
});
this worked for me, make sure to wrap your json in the file with jsoncallback("your jason here");
This is killing me. Trying to load data from a different domain from an API-sorts of that I'm trying to write. When sending JSON parameters as POST they get discarded, I've read somewhere that some special headers must be set before_filter:
def cors_headers #set_access_control_headers
headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
headers['Access-Control-Max-Age'] = "1728000"
headers['Access-Control-Allow-Headers'] = 'content-type, accept'
end
Haven't had any luck with these though. Guess it's a browser limitation.
When I try sending the data as GET instead of POST, it gets added to the URL like this:
Completed in 959ms (View: 0, DB: 2) | 200 OK [http://www.somedomain.com/connector/browse/Sport.json?callback=jQuery16105855946165975183_1379526705493&{%22filters%22:[{%22filter%22:{%22attribute%22:%22id%22,%22op
erator%22:%22%3E%22,%22value%22:%222%22}},{%22filter%22:{%22attribute%22:%22id%22,%22operator%22:%22%3C%22,%22value%22:%227523%22}}]}&_=1379526723982]
So Rails basically can't see the filters which are the params that I'm trying to send
Parameters: {"{\"filters\":"=>{}, "id"=>"Sport", "_"=>"1379526723982", "callback"=>"jQuery16105855946165975183_1379526705493"}
The jquery snippet I'm playing with is:
$jq.ajax({url: "http://www.somedomain.com/connector/browse/" + x + ".json" + "?callback=?",
type: "get", // tried post too
dataType: "json", // tried jsonp too
accepts: "json",
data: req_data, // this is JSON.stringified already
processData:false,
contentType: "application/json; charset=UTF-8;",
success: output
});
The sample data I'm trying to send is this
{"filters":[{"filter":{"attribute":"id","operator":">","value":"2"}},{"filter":{"attribute":"id","operator":"<","value":"7523"}}]}
Has anyone an idea on how to sort this out?
Muchos gracias!
Basically the JS SOP prevents us from sending a POST request and reading the response, but this can be worked around like this:
1) Compose the request data, send it as POST. Don’t expect to receive a response. Don’t use on success, use on complete instead. Add a random-ish variable to the request
2) Temporarily store the response on the server side in a file or session variable or memcached server, use the random var mentioned above as key within the store.
3) send a 2nd JSON AJAX call to fetch the cached object.
With memcached, make sure the cached responses get removed from time to time or expire, in my case the app gets a lot of traffic, it would spam my memcache servers with junk if not set to expire.
here's some sample code
I am facing this strange error in using $.post.
works
$("#add-video").click(function(){
var url = $("#new-video-url").val();
$('#loader').show();
$.post( base_url + "forms/coach/get_url.php", { url:url, base_url:base_url }, function(data){
alert(data);
$('#loader').hide();
});
});
The above piece of code, shows me the json array I am receiving using a php file, and also shows the title field here, and hides the loader image.
But when I alert(data.title), it shows me undefined. More over, when I add datatype 'json' to $.post,
doesn't work
$("#add-video").click(function(){
var url = $("#new-video-url").val();
$('#loader').show();
$.post( base_url + "forms/coach/get_url.php", { url:url, base_url:base_url }, function(data){
alert(data);
$('#loader').hide();
}, "json"); //Added datatype here.
});
This neither alerts anything nor does it hide the loader image. I also tried,
$("#add-video").click(function(){
var url = $("#new-video-url").val();
$('#loader').show();
$.post( base_url + "forms/coach/get_url.php", { url:url, base_url:base_url }, function(data){
jQuery.parseJSON(data);
alert(data.title);
$('#loader').hide();
});
});
The above one too neither alerts anything nor does it hide the loader. And then I tried this one too that did nothing.
$("#add-video").click(function(){
var url = $("#new-video-url").val();
$('#loader').show();
$.post( base_url + "forms/coach/get_url.php", { url:url, base_url:base_url }, function(data){
jQuery.parseJSON(data); //tried without this too.
alert(data['title']);
$('#loader').hide();
});
});
The strangest thing is that I have previously used json as I have shown in the 2nd script(out of 4), and that works normally. My JS console too doesn't show any errors or warning. What am I doing wrong here? How do I access the title field of data?
If this helps, here is how I send the json array,
$json = array("title" => $title, "embed" => $embed, "desc" => $desc, "duration" => $duration, "date" => $date);
print_r(json_encode($json));
I would really appreciate if someone can point out the error and tell me why my scripts are failing, similar functions worked in other js file.
here is my data, that is returned by server,
{"title":"Sunn Raha Hai Na Tu Aashiqui 2 Full Song With Lyrics |
Aditya Roy Kapur, Shraddha Kapoor","embed":"\r\t\t\t\t\t\r\t\t\t\t\t</param></param>\r\t\t\t\t\t</param>\r\t\t\t\t\t\r\t\t\t\t\t</embed></object>","desc":"Presenting
full song \"Sun Raha Hai Na Tu\" with lyrics from movie \"Aashiqui 2\"
produced by T-Series Films & Vishesh Films, starring Aditya Roy Kapur,
Shraddha Kapoor in voice of Ankit Tiwari. \n\nSong: SUNN RAHA
HAI\nSinger: ANKIT TIWARI\nMusic Director: ANKIT TIWARI\nAssistant Mix
Engineer - MICHAEL EDWIN PILLAI\nMixed and Mastered by ERIC PILLAI
(FUTURE SOUND OF BOMBAY)\nLyrics:SANDEEP NATH\nMovie: AASHIQUI
2\nProducer: BHUSHAN KUMAR KRISHAN KUAMR Producer: MUKESH BHATT
\nDirector: MOHIT SURI\nMusic Label: T-SERIES\n\nBuy from iTunes -
https://itunes.apple.com/in/album/aashiqui-2-original-motion/id630590910?ls=1\n\nEnjoy
& stay connected with us!! \n\nSUBSCRIBE T-Series channel for
unlimited entertainment\nhttp://www.youtube.com/tseries\n\nCircle
us on G+ \nhttp://www.google.com/+tseriesmusic\n\nLike us on
Facebook\nhttp://www.facebook.com/tseriesmusic\n\nFollow
us\nhttp://www.twitter.com/_Tseries","duration":"391","date":"2013-04-03"}
Edit
This worked suddenly.. :o
$("#add-video").click(function(){
var url = $("#new-video-url").val();
$('#loader').show();
$.post( base_url + "forms/coach/get_url.php", { url:url, base_url:base_url }, function(data){
alert(data.desc);
console.log(data.desc);
$("#loader").hide();
}, "json");
});
In comments, you mention that this AJAX corresponds to a YouTube API.
YouTube's blog announced in 2012 that they would support CORS, which uses server-side header flags that compatible browsers interpret as permitting requests that would otherwise be prohibited by browser security Same-Origin-Policy.
Assuming, as you say, the first example worked, the first issue was "Why did (a subsequent) alert(data.title) fail? (my edit) ". If you type alert(data.title) in the console, it will fail because the scope of data is the callback function where it is defined as a parameter, and in the global scope data is undefined. If you try to pass data back to the global scope somehow, it can still be undefined because $.post returns immediately, before the data has been fetched, and merely queues a request and sets the callback function you supply to handle the reply.
The second example, which explicitly sets the $.post dataType parameter to 'json', may fail with CORS based API because the mime types for json are not allowed to be sent up to the server as Content-Type: for a simple CORS request, and $.post will as far as I know only do simple requests without preflight. $.ajax can possibly do the more complex requests if correctly applied.
The work around to keep using $.post is not to use json as the expected data type, send requests up as form data, the server may send you back json anyway if that is what the API says will happen, which can be verified while testing the code.
From https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS
Simple requests
A simple cross-site request is one that:
Only uses GET, HEAD or POST.
If POST is used to send data to the
server, the Content-Type of the data sent to the server with the HTTP
POST request is one of application/x-www-form-urlencoded,
multipart/form-data, or text/plain.
Notice that application/json did not make the list of what Content-Type is permissible in a simple CORS request.
See also A CORS POST request works from plain javascript, but why not with jQuery?
Use ajax as
$.ajax({
url:url,
type:'post',
dataType:'json',
success:callback
})
With this type you can set lots of parameter in low level.
With datatype attribute jQuery parses JSON and send data as callback function.
I think you have to replace all single \ with double '\' to feed it to JSON.parse.
I have read a lot of topics about CORS & Javascript and about changing the headers in your post but I can't find the right example I am looking for.
So I'm going to first up start with explaining the situation:
I can not change anything to the webserver since this is out of my reach (It's a SAP Cloud Portal)
I can only change the POST code, so I can only control what I send.
The problem I have is described in the following Post:
jQuery $.ajax(), $.post sending "OPTIONS" as REQUEST_METHOD in Firefox
--> My FF & Chrome Headers send a METHOD OPTIONS instead of METHOD POST.
I have written example code that works in IE but not in FF & Chrome:
var dataString = "<result><firstname>example</firstname><lastname>ThisIsSparta</lastname></result>";
var urlString = "http://delyo001.you.local:8000/sap/bc/youconsulting/ws/rest/anonymous/z_names_post";
//Add TO SAP.
var aData =
jQuery.ajax({
type: "POST",
contentType: "application/xml",
url: urlString, // for different servers cross-domain restrictions need to be handled
data: dataString,
dataType: "text",
success: function(xml) { // callback called when data is received
//oModel.setData(data); // fill the received data into the JSONModel
alert("success to post");
},
error: function(xml) { // callback called when data is received
//oModel.setData(data); // fill the received data into the JSONModel
alert("fail to post");
}
});
});
Or
var invocation = new XMLHttpRequest();
var url = 'http://delyo001.you.local:8000/sap/bc/youconsulting/ws/rest/anonymous/z_names_post';
var body = '<result><firstname>perthyrtyrtygop</firstname><lastname>sparta</lastname></result>';
invocation.open('POST', url, true);
invocation.setRequestHeader('X-PINGOTHER', 'pingpong');
invocation.setRequestHeader('Content-Type', 'application/xml');
invocation.send(body);
I have found 2 ways to fix this but without any examples:
- do something with a proxy?
- send specific headers
More information about my problem can be found at:
- http://scn.sap.com/message/13697625#13697625
If you can't set the right headers on the server-side and you can't modify the response for jsonP you should indeed use a proxy.
A proxy script is a sort of middleware. You make a request to the script the script gets the data, and returns it to you. For example php proxy. You can make the same thing in asp, jsp, flash or even java applet.
Now you have your SAP service, a proxy (php)file in a your prefered location, and your local javascript in the same domain as the proxy. You don't even need CORS.
If you want to put the proxy in another domain you have to make sure the php file sends the right headers. (Access-Control-Allow-Origin yourdomain or Access-Control-Allow-Origin * for allow all)