25

So I'm trying to make a request to the Stack Exchange API with the following jQuery code:

$.ajax({                                                                                                                                                                                                        
    type: 'POST',                                                                                                                                                                                                 
    url: 'http://api.stackoverflow.com/1.1/stats',                                                                                                                                              
    dataType: 'jsonp',                                                                                                                                                                                                
    success: function() { console.log('Success!'); },                                                                                                                                                                                       
    error: function() { console.log('Uh Oh!'); }                                                                                                                                                              
});   

But when I open the file on my machine, in either FireFox or Chrome, and make the request, I get this error:

Resource interpreted as Script but transferred with MIME type application/json.
Uncaught SyntaxError: Unexpected token :
Uh Oh!

I don't have a clue what's going on. I know the Stack Exchange API Gzips its responses, would this cause any trouble?

hichris123
  • 10,145
  • 15
  • 56
  • 70
theabraham
  • 15,840
  • 9
  • 42
  • 41
  • What do you get from the server? I get JSON - and JSON is not JSON-P, which encapsulates the data in a callback function, which must be in your global namespace, and which you told the server about in your request (something else I don't see in your code). The point is, just don't tell your jQuery the result is JSONP if really it is JSON. – Mörre May 18 '11 at 14:06
  • 3
    I used JSONP because it was suggested elsewhere on StackOverflow. When I use JSON I get this error: `XMLHttpRequest cannot load http://api.stackoverflow.com/1.1/stats. Origin null is not allowed by Access-Control-Allow-Origin.` – theabraham May 18 '11 at 14:08
  • Don't know their API, but what is returned from that URL clearly is JSON, as I said. With "dataType" you only tell *your jQuery* how to interpret the result, you don't tell the *server* that you want JSONP. – Mörre May 18 '11 at 14:11

2 Answers2

21

You have to set an unconventional parameter to get the SO API to work. Rather than the conventional callback, you need to pass a jsonp parameter.

Furthermore, you can't do POST with JSONP.

$.ajax({                                                                                                                                                                                                        
    type: 'GET',                                                                                                                                                                                                 
    url: 'http://api.stackoverflow.com/1.1/stats',                                                                                                                                              
    dataType: 'jsonp',                                                                                                                                                                                                
    success: function() { console.log('Success!'); },                                                                                                                                                                                       
    error: function() { console.log('Uh Oh!'); },
    jsonp: 'jsonp'                                                                                                                                                
});

It is not possible to do cross-domain AJAX using the conventional XMLHTTPRequest. This is for security reasons (it's call the same-origin policy).

There is a workaround. script tags are not subject to this restriction. This means that you can insert a script tag into the document that calls a URL. If you define a globally-accessible function in your script and tell the remote server what that function is called, the server can pass code that wraps the data to be sent in a call to that function.

The difficulty you had here is with the StackOverflow API. Conventionally, you would use the callback argument in your request, to tell the server what your function is called. However, StackOverflow's API asks you to use the jsonp parameter instead.

lonesomeday
  • 233,373
  • 50
  • 316
  • 318
  • 1
    "jsonp" is the parameter - but its value is the name of a function in ones global namespace, which gets called once the results are in. – Mörre May 18 '11 at 14:15
  • As I said, see comments to your Q, you have to tell THE SERVER that you want JSONP, or it sends you JSON! how depends on the server, this one wants a parameter "jsonp" with the name of the callback function. – Mörre May 18 '11 at 14:17
  • @Mörre Not true. jQuery automatically generates the global function. If an API demands a parameter other than `callback` (as StackOverflow does), you need to tell it what parameter to use with the `jsonp` setting. – lonesomeday May 18 '11 at 14:17
  • 1
    That's nice for jQuery - I told (and showed) him what the SERVER wants. Isn't it better to know the background rather than how one specific library implements it??? "I only learned to press RED buttons, but this one is gren, so I can't turn on the light, so sorry". Just joking :) (well, not quite) – Mörre May 18 '11 at 14:18
  • @Mörre Oh for goodness sake. If you don't put in a `jsonp` parameter, jQuery sends a `callback=func` GET parameter, where `func` is the name of the global function. If I say `jsonp: 'jsonp'`, jQuery sends a `jsonp=func` parameter. That is required by the StackOverflow API. – lonesomeday May 18 '11 at 14:20
  • 1
    Yes, we all know that, and your point is? See above, I think I said everything. You prefer to tell him ONLY about jquery (granted, that was he question) - while I prefer to broaden the scope to tell him how it ACTUALLY WORKS, independent of the lib being used. – Mörre May 18 '11 at 14:21
  • @Mörre I haven't got the faintest idea what you're trying to correct. My code is correct; it works. – lonesomeday May 18 '11 at 14:23
  • I'm not trying to CORRECT, and I didn't write a single line meant for YOU. I'm trying to TEACH (but not YOU, you didn't ask anything and I never claimed you made a mistake either). I wrote that, reading helps, you know. Your code works, and he can copy and paste, but he won't be any wiser. I *explained*, or at least I tried to. Over and OUT. – Mörre May 18 '11 at 14:24
  • @Mörre Oh for goodness' sake. I was trying to write it as an edit, but your bizarre comments distracted me! See the edit (which has a notable lack of shouting.) – lonesomeday May 18 '11 at 14:27
  • 1
    Woh, woh! I appreciate the help from both of you. I think a library/api specific question was appropriate this time around. I never knew of JSONP before hand and was annoyed when my JSON requests weren't working (when other API's would work without a hitch.) I got to a point where I was just kind of shotgun debugging to solve this problem; however, I found [this post](http://stackoverflow.com/questions/2067472/please-explain-jsonp) helpful in explaining what JSONP does. – theabraham May 18 '11 at 14:29
  • Got en error after executing the same code as above. SyntaxError: expected expression, got '<'. – Debaprasad Jana Feb 26 '16 at 10:58
  • @DebaprasadJana Sounds like your server doesn't support JSONP. – lonesomeday Feb 26 '16 at 15:23
  • I am using Apache Tomcat 7.0.55. Please suggest how to overcome this problem so that I can connect to a cross domain page (ex: 'http://api.stackoverflow.com/1.1/stats') from my application using above code. – Debaprasad Jana Feb 26 '16 at 15:35
  • @DebaprasadJana Ah, I see what you mean. The script referenced in the OP and quoted in my answer is now disabled. See https://api.stackexchange.com/docs/api-v1-shutdown You'll need to use an API that hasn't been disabled... – lonesomeday Feb 26 '16 at 16:12
4

Try this URL: http://api.stackoverflow.com/1.1/stats?jsonp=callme

"callme" is the name of your callback function - in your GLOBAL NAMESPACE (window object).

By the way, if you are running Firefox and have the JSONView add-on installed you can test the above URL (and yours for comparison) directly.

Result from calling the URL:

callme({
  "statistics": [
...
  ]
})
Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Mörre
  • 5,699
  • 6
  • 38
  • 63