views:

258

answers:

2

I am trying to call to the bit.ly URL shortening service using jQuery with an .ajax call.

update I wondering if this is a cross-domain security issue? I'm making a call from mysite.com to bit.ly

<html><head>
<script type="text/javascript" src="http://www.twipler.com/settings/scripts/jquery.1.4.min.js"&gt;&lt;/script&gt;
<script type="text/javascript">
jQuery.fn.shorten = function(url) 
{ 
  var resultUrl = url;

  $.ajax(
  {
     url: "http://api.bit.ly/shorten?version=2.0.1&amp;login=twipler&amp;apiKey=R_4e618e42fadbb802cf95c6c2dbab3763&amp;longUrl=" + url,
     async: false,
     dataType: 'json',
     data: "",
     type: "GET",
     success: 
     function (json) {  resultUrl = json.results[url].shortUrl; } 
     });

   return resultUrl;
} ;
</script></head><body>
<a href="#" 
      onclick="alert($().shorten('http://amiconnectedtotheinternet.com'));"&gt;
      Shorten</a>   </body>    </html>

This works in IE8 but does not work in FireFox (3.5.9) nor in Chrome. In both cases 'json' is null.

Headers in IE8

GET http://api.bit.ly/shorten?ver..[SNIP]..dtotheinternet.com HTTP/1.1
Accept: application/json, text/javascript, */*
Accept-Language: en-US
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0;
      SLCC2; .NET CLR 2.0.50727; Media Center PC 6.0; InfoPath.2; 
     .NET CLR 1.1.4322; .NET CLR 3.5.30729; .NET CLR 3.0.30729)
Host: api.bit.ly
Connection: Keep-Alive

Headers in Chrome

GET http://api.bit.ly/shorten?versio..[SNIP]..nectedtotheinternet.com HTTP/1.1
Host: api.bit.ly
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.5 
    (KHTML, like Gecko) Chrome/4.1.249.1045 Safari/532.5
Origin: file://
Accept: application/json, text/javascript, */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3 

So the only obvious difference is that Chrome is sending "Origin: file://" and I've no idea how to stop it doing that.

+1  A: 

Use Fiddler to verify the actual payload of the request and the response from the bit.ly service. Compare the IE request/response with the Chrome one to identify what's different.

My (wild) guess would be that the service is returning you an error message when the request is sent by Firefox and Chrome due to differences in how the browsers make the request. In particular, the way you append the url parameter seems a bit suspicious to me, and I'd url encode it just in case.

Update: So indeed the HTTP headers have revealed the problem. :-)

The Origin header is added by an user agent when it wants to suggest the website that the request is cross-origin request. Apparently Chrome has added support for this header recently. And of course:

The details of the Origin header are still being finalized. We will update the implementation in Google Chrome as the specification evolves based on feedback from Mozilla and from the W3C and IETF communities at large.

It might turn out that you can't currently do anything to prevent Chrome from sending that header. Btw, seems that the Origin header was first introduced by Firefox 3.6 and I suspect you are one of those people that run all the latest and greatest of all browsers. :-)

Btw, XMLHttpRequest does have cross-domain restrictions. So, I wonder if jQuery.Ajax is not using the new XDomainRequest on IE8 instead of the XMLHttpRequest.

But back to your problem - at this point everything points to the only solution available would be to make the Ajax call to your site and make the bit.ly call from your server. Not optimal, I know...

Franci Penov
Thanks for the tips, I'll try them later. Interestingly if you just paste the request URL into IE/FF/Chrome you get a valid response :(
Dead account
I would assume that the address filed (at least the IE one for sure) in all browsers does the proper url encoding of the parameter. However, I wouldn't be surprised if the implementation of the XMLHttpRequest in Firefox and Chrome expects the calling code to do it and passes the URL as they see it. This might actually be intentional, as per the URI RFC (3896 or 3986 - I always forget exact number), query parameters are allowed in the middle of the path, so there's no 100% way to know if the URL in the parameters is not part of the path and should not be encoded.
Franci Penov
I added the URLEncode plugin and encoded the URL. Still no joy. I might be quicker going for a work around and calling bit.ly from my website, and calling my website from jQuery.
Dead account
Did you look at the actual HTTP request/response in Fiddler? As I said, the bit about the URL parameter encoding was a wild guess. You should try to investigate what exactly is the difference between the IE and Firefox calls to figure out the actual problem.
Franci Penov
Updated the question with the headers. Still not getting anywhere. Will add a bounty tomorrow.
Dead account
Thanks for your help and excellent explanation. I do keep Chrome and FF up to date. I'll have the request come to my site which actually makes life easier (long story short; it's for a twitter app' and I want to make option for bit.ly is.gd etc) Many thanks
Dead account
+1  A: 

The quick and lazy way to get this to work is to use JSONP.

i.e.

$.ajax(
{
     url: Request,
     async: false,
     dataType: 'jsonp',
     data: "",
     type: "GET",
     success: 
     function (json) {  console.log(json.data.url); } 
});

Should work in everything.

Chris M