Backbone js with JSONP - javascript

I have a simple backbone application, which has struts controller as its backend and it was working fine. Then I tried to include cross domain request handling logic and I came to know that there are 2 ways to make cross domain request
JSONP
CORS
Now what I'm trying to do is, if the browser is not supporting CORS.. Then I'll have to make JSONP request. I'm done with CORS (just added header using filter) and this part is working, but I'm not able to make JSONP request successfully.
My questions regarding this are:
What should be the response from server (struts controller) be? Does it return something like function call? As of now it is returning model.
In Backbone js, overriding only the Backbone.sync to have its datatype as JSONP is enough?
Note: I'm getting the following error for my JSONP call:
Error: jsonpCallback was not called
Code: I overrided my sync in collection. My Sync function is
sync: function(method, model, options) {
options.dataType = 'jsonp';
options.url="http://localhost:8084/CrossDomain_backbone/messages.json";
//options.contentType='application/json-p';
options.error=this.errorr;
return Backbone.sync(method, model, options);
}
,
parse: function(resp){
alert('inside parse..');
return resp.model;
},
errorr:function(response,responseText)
{
alert('inside callback..: ' + responseText);
},
Thanks.

Your Struts code will need to return a function call which contains the data.
The url request might look something like this:
options.url="http://localhost:8084/CrossDomain_backbone/messages.json?callback=?";
The callback part of the query string will automatically be substituted with a random function name that your Struts code will need to use.
For example, when the JSONP request is made, jQuery (used by Backbone) might look like this:
http://localhost:8084/CrossDomain_backbone/messages.json?callback=jQuery17205394351207651198_1336231056100
So, your Struts code will read the callback parameter and emit JavaScript something like this:
jQuery17205394351207651198_1336231056100({
"name": "Henry T Ford",
"company": "Ford Motor Company",
"modified": "2012-04-05T15:06:36Z"});
jQuery handles creating a temporary function with that random name to receive the response and pass it to the defined success method.

Related

BackBone - best way to send a server request

I'm new to Backbone and am just getting familiar with it.
I have a model and a collection - and view to the collection and a Form.
I'm sending request to get/get all/create by doing form.submit(), or something similar - which calls for the correct type [GET/POST/PUT] to the server using the base URL in the collection/model.
how do i send a non-trivial request? say that my base URL is /some/url , and i want to send /some/url/doSomething. should i directly send an ajax request with this URL or does backbone handle this in a more simpler way?
Thanks!
In backbone, you can pass url as an option to your model.fetch, model.save requests, etc to override the default declared in the model. You don't need to manually form an ajax request with $.ajax or anything like that.
If your URL does not pertain to a particular resource/model/collection, you may use raw jQuery ajax requests.
$.ajax({
method: 'GET',
url: '/some/url',
success: function(resp) { //handle response}
})
Best example of REST API is github api
example of merge a pull request (Merge Button):
PUT /repos/:owner/:repo/pulls/:number/merge
The main goal is using resources instead a commands. For example:
REST:
PUT /repos/:owner/:repo/pulls/:number/merge
{"commit_message":"mesg"}
NO-REST:
POST /merge
{"commit_message": "mesg", "owner": 123, "repo":"asd", "number": 1}
Cheers

Cookies being passed when loading resource but not ajax?

Setup is I have one Rails app setup to act as an JSON API and another static html page that I want to use to call the API. For sake of argument the rails API is at foo.com and the static html page is at bar.com.
On the foo.com app I have something like this:
if !cookies[:foo]
cookies[:foo] = "testing #{rand(500)}"
else
logger.info(cookies[:foo])
render :json => { :cookie => cookies[:foo] }
When I try to do a ajax GET request with jquery from bar.com the cookie does not get sent back to the JSON API.
$.get('http://foo.com/', function(data){console.log(data)})
But If I load the page a resource I can get the cookies to send back and forth between foo.com and bar.com
<script type="text/javascript" src="http://foo.com"></script>
Does anyone know why I am able to pass cookies back and forth cross-domain when loading the script as a script resource and not when I do a simple ajax request? Any way around this?
Use $.ajax as you need to make a JSONP request coz your ajax call is cross site.
$.ajax({
url: "xxxx",
crossDomain : true,
dataType : 'json',//if response is in JSON Notation
success : function (result){
alert(result);
}
});
Just as techie said, you need to use $.ajax and make a json(p) request in order for cross domain to be enabled.
Cookies are tricky with this sort of implementation though. even if you manage to send your cookies back and forth using some sort of hack, older (or cheaper) browsers will block them.
*cough* IE *cough*
A simple way to "hack" around this is to pass the cookie in the url, like so:
$.ajax({
url: "//domain.com/path/to/stuff;cookie1=value1?someParameter2=value2",
crossDomain : true,
dataType : 'json',//if response is in JSON Notation
success : function (result){
alert(result);
}
});
In this example, I've told my server that my request has a cookie name "cookie1" with a value of "value1" and a GET parameter with a value of "value2"
Hope this helps.

"Security Err: Dom Exception" thrown when nesting ajax calls

Here's the issue. I'm extracting gmail contacts through an ajax call in javascript/jquery like this:
function getUserInfo() {
var xml_parse = "";
$.ajax({
url: SCOPE + '?max-results=9999&access_token=' + acToken
data: null,
success: function (resp) {
xml_parse = $.parseXML(resp);
callGmailHelperWebService(xml_parse);
},
dataType: "jsonp"
});
}
function callGmailHelperWebService(xml_parse) {
GmailHelperService.ConvertXMLToList(xml_parse, onSuccess, onFailed, null);
}
So, as you can see, if the initial ajax call is successful, i call a function which calls a web service that sits on the save server as my project (in fact, it's part of the project).
My web service (GmailHelperService) is wired up correctly, as I can definitely call it in other places (like right after this ajax call, for example). However, when I try to call it within the "success" portion of the ajax call, i get the following error:
Uncaught Error: SECURITY_ERR: DOM Exception 18
My theory is that this has something to do with cross-domain issues, but I can't understand why. And I certainly can't figure out how to fix this.
I'd appreciate any help.
JSONP is a data transfer method that involves sending your data in this format:
callback({"foo":"bar"});
As you can see, this is NOT xml. It is JSON wrapped in a callback method that will get executed when the request is done loading, thus allowing it to be cross-domain because it can be requested using a <script> tag.
You cannot simply change your dataType to JSONP and return xml, expecting it to work. XML != JSONP. You can however return XML in jsonp, for example, callback({"xml","... xml string here "}) but be mindful of quotes, all json keys and values must be wrapped in double quotes, inner-quotes need to be handled appropriately.
If your request is a same domain request (Same protocol, same subdomain, same domain, and same port,) then you can change your dataType to "XML" if you are returning XML. Otherwise, you need to either setup a proxy script to get the xml for you, or have your webservice return JSONP.
For example, the following urls are all considered cross-domain from each other.
http://example.com
http://www.example.com
https://example.com
https://www.example.com
http://example.com:8080
All of the above urls would be considered cross-domain, even if they are on the same server.

Problems reading json data with jquery.

I am having problems using jquery to grab json data from a web service that lies on a different subdomain from where my client side code is. When I access the exact same json data from a local text file, my code works fine.
The json data is coming from this address
var jsonFeed = https://crm.bmw.ca/webservices/RetailerLocator.ashx?language=en&callback=?
The MIME type of the data is text/html, however I have also tried application/json.
Here is one method of access
$.getJSON(jsonFeed, function (data) {
$.each(data, function (i, item) {
alert(item);
});
});
I've also tried this method, which came back with a parsererror. I've also tried this with a jsonp datatype
$.ajax(jsonFeed, {
crossDomain: true,
dataType: "json",
success: function (data, text) {
$.each(data, function (i, item) {
alert(item);
});
},
error: function (request, status, error) {
alert(status + ", " + error);
}
});
My code has to be entirely client side so a proxy isn't an option right now.
An example of someone with a very similar problem can be found here.
jQuery AJAX JSON dataType Conversion
You can only work within the confines of what is possible. Same-origin policy can't be subverted, although you can use things like cross-domain policy headers on each of your servers to essentially link them together. However, that's only supported in the newer crop of browsers, and you have to control all the servers in the network.
See: http://en.wikipedia.org/wiki/Same_origin_policy for more information on what you're up against.
While the returned JSON data should probably be of type text/json, the bigger problem is that the API call is not respecting your "callback" parameter. Since you're calling the API cross-domain you have to use JSONP which means your data should be returned inside of a function call. For example, if you navigate to https://crm.bmw.ca/webservices/RetailerLocator.ashx?language=en&callback=mycallback you should see something like this returned:
mycallback([{"RetailerID":1110,"Name":"BMW St. John's","Address":"120 Kenmount Road"...)
The fact that the callback function name specified in the "callback" argument isn't showing up as part of the returned data probably means that you're using an incorrect name for that parameter. Or, it could be that the system is not configured to allow cross-domain requests. You should contact the system admin and make sure the API allows cross-domain requests and also check the docs for that API and make sure you're using the correct callback parameter name.
So far as I can tell from playing with JSFiddle (http://jsfiddle.net/CEDB5/), the question/answer you mentioned is correct: unless crm.bmw.ca starts sending the correct MIME type you are stuck.

How to use JSONP to overcome XSS issue?

I have a piece of javascript executing on a jetty server which is sending a XMLHTTPRequest to a scoket on another server(wamp server). The request gets sent to the socket, however the XHR response seems to be getting blocked.
I have heard that I can use JSONP to overcome this problem.
However as I am new to both javascript and I have never used JSONP technique before I would greatly appreciate any help in how to use this technique?
function sendPost(url, postdata, callback) {
xmlHttp=GetXmlHttpObject()
if (xmlHttp==null) {
alert ("Browser does not support HTTP Request")
return
}
xmlHttp.onreadystatechange=callback
xmlHttp.open("POST",url,true)
xmlHttp.send(postdata);
}
function sendInitRQ(width, height) {
var post = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><command type=\"init\"><width>" + width + "</width><height>" + height + "</height></command>";
sendPost("http://localhost:80/socket.php", post, initReturned);
}
I know that the php socket is recieving the post as when i check the server log i get a 200 on the get request.
I just want to know how can I use the JSONP approach?
I have seen exampples of the approach but Iam stilll unsure of how to do it.
The JSONP technique uses a completely different mechanism for issuing HTTP requests to a server and acting on the response. It requires cooperating code in the client page and on the server. The server must have a URL that responds to HTTP "GET" requests with a block of JSON wrapped in a function call. Thus, you can't just do JSONP transactions to any old server; it must be a server that explicitly provides the functionality.
The idea is that your client-side code creates a <script> block dynamically, with the "src" attribute set to the URL of the JSONP server. The URL should contain a parameter telling the server the name of the Javascript function you expect it to call with the JSON data. (Exactly what parameter name to use depends on the server; usually it's "callback", but I've seen some that use "jsonp".) The client must of course have that function in the global scope. In other words, if you have a function like
function handleJSON(json) {
var something = json.something;
// ... whatever ...
}
then your URL tells the server to call "handleJSON", and the server response should look like this:
handleJSON({"id": 102, "something": { "more": "data", "random": true }});
Thus when the <script> block is loaded from the "src" URL you gave, the browser will interpret the contents (the response from the server) and your function will be called.
It should be clear that you should only make JSONP requests to servers you trust, since they're sending back code to execute in your client, with access to any active session(s) your client has with other secured sites.
edit — Here's a nice article: http://www.ibm.com/developerworks/library/wa-aj-jsonp1/

Categories

Resources