Duncan Johnson Duncan Johnson - 7 months ago 30
Javascript Question

jQuery.ajax call returns an empty data container but the raw URL works

I'm using a Greasemonkey script to pull data from the RSS feed http://www.instapaper.com/folder/48337/rss/11185/QBV0RZfH4KBO7GwgrR3D8b7sv90 and insert it into a page with jQuery. The address returns valid RSS, but when Greasemonkey fires an Ajax call (see below) it always returns an empty request and fires the error callback. What am I missing in my Ajax call?

$.ajax({
url: "http://www.instapaper.com/folder/48337/rss/11185/QBV0RZfH4KBO7GwgrR3D8b7sv90",
dataType: "xml",
data: "",
type: "GET",
success: function (data){
var classString = "";

$("item",data).each(function (i) {
classString = classString + "<li><a href='" + $("link",this).text() + "'>" + $("title",this).text() + "</a></li>";
});

var message = "<div id='classes'><h2>Class Links</h2><ul>" + classString + "</ul></div>";
$("#sidelinks").prepend(message);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
$("#sidelinks").prepend("<div id='classes'><h2>Class Links</h2><p>There was an error accessing class link information.</p></div>");
}
});


I'm not quite sure if this is it, but my
jQuery.ajax
call seems to issue a different type of HTTP call than when I simply paste the RSS URL into my location bar. Even though I specify that the request is to be a "GET", jQuery seems to be sending an "OPTIONS" request. Below is the output trapped with Live HTTP Headers for the call issued by my Ajax request and for the working request by entering the URL into the location bar--

This one fires the Ajax error callback with an empty (?) response object:

http://www.instapaper.com/folder/48337/rss/11185/QBV0RZfH4KBO7GwgrR3D8b7sv90

OPTIONS /folder/48337/rss/11185/QBV0RZfH4KBO7GwgrR3D8b7sv90 HTTP/1.1
Host: www.instapaper.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Proxy-Connection: keep-alive
Origin: http://home.bju.edu
Access-Control-Request-Method: GET
Access-Control-Request-Headers: x-requested-with

HTTP/1.x 200 OK
Date: Thu, 27 Aug 2009 15:16:53 GMT
Server: Apache
P3P: CP="ALL ADM DEV PSAi COM OUR OTRo STP IND ONL"
Vary: Accept-Encoding
Content-Type: text/xml; charset=utf-8
Content-Length: 1210
Age: 0


This successfully displays data in the browser (what happens when I drop URL in address bar):

http://www.instapaper.com/folder/48337/rss/11185/QBV0RZfH4KBO7GwgrR3D8b7sv90

GET /folder/48337/rss/11185/QBV0RZfH4KBO7GwgrR3D8b7sv90 HTTP/1.1
Host: www.instapaper.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.2) Gecko/20090729 Firefox/3.5.2 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Proxy-Connection: keep-alive

HTTP/1.x 200 OK
Date: Thu, 27 Aug 2009 15:18:04 GMT
Server: Apache
P3P: CP="ALL ADM DEV PSAi COM OUR OTRo STP IND ONL"
Vary: Accept-Encoding
Content-Type: text/xml; charset=utf-8
Content-Length: 1210
Age: 0

Answer

I was loading jQuery into an unsafeWindow object, so I'm guessing that my problem with Greasemonkey firing OPTIONS requests relates to it not being allowed to use the XMLHttpRequest that jQuery uses.

I was able to successfully issue a GET by switching from using jQuery.ajax to using a regular Greasemonkey GM_xmlhttpRequest call. I still use jQuery in the response callbacks. Below is an abbreviated example of what I'm doing with the old lines commented out.

//$.ajax({
GM_xmlhttpRequest({
    url: "http://www.instapaper.com/folder/48337/rss/11185/QBV0RZfH4KBO7GwgrR3D8b7sv90",
    //dataType: "xml",
    //data: "",
    //type: "GET",
    method: "GET",
    //success: function (data){
    onload: function (responseObject){
          var data = responseObject.responseText;

          // Same code as in my question, use some jQuery selectors here to parse the data...
    },
    //Error: function (XMLHttpRequest, textStatus, errorThrown) {
    onerror: function () {
      // Same code as in my question...
    }
});

(I found part of the answer to my question in Stack Overflow question [Load remote URL with Greasemonkey and jQuery][1].)