2

I'm trying to use an API which requires a call to get a Json with basic HTTP authentication. I'm not brilliant with javascript.

The code which I have is:

    <script type="text/javascript">

    $.getJSON({
        'url': 'http://data.unistats.ac.uk/api/KIS/Institutions.JSON?pageIndex=1&pageSize=25',
        'beforeSend': function(xhr) {
            xhr.setRequestHeader("Authorization",
                "Basic " + encodeBase64("ABCDEF" + ":" + password));
        },
        success: function(result) {
            alert('done');
        },
        error: function(result) {
            alert('no');
        }
    });
    </script>

I expect that this would call one of either success, or error. So the output should be either an alert saying "done", or an alert saying "no". Or even an error in the developer console to tell me what is wrong.

I don't get anything, neither alert shows and I have no errors in the console. Any ideas what is happening here?

Thanks,

Edit: Using firebug I see the request headers are: The request headers show up as:

OPTIONS /api/KIS/Institutions.JSON?pageIndex=1&pageSize=25 HTTP/1.1
Host: data.unistats.ac.uk
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0
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
Origin: null
Access-Control-Request-Method: GET
Access-Control-Request-Headers: authorization
Connection: keep-alive

This doesn't seem correct as it should be: Authorization: basic TheSecurityKey

The response is 405, method not allowed Reload the page to get source for: http://data.unistats.ac.uk/api/KIS/Institutions.JSON?pageIndex=1&pageSize=25

Response headers:

HTTP/1.1 405 Method Not Allowed
Cache-Control: private
Allow: GET
Content-Length: 1725
Content-Type: text/html; charset=UTF-8
Server: Microsoft-IIS/7.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Fri, 16 Aug 2013 21:00:11 GMT

When I try from a server I have set up

Can be seen here: http://spindroid.co.uk/tt/byUniversity.html

Partial Solution

Using jsonp it receives a response, but the headers aren't attached and so I am missing authentication.

            <script type="text/javascript">


$(document).ready(function () {
jQuery.support.cors = true;
$.ajax({
        'type': "GET",
        'dataType': 'jsonp',
        'url': 'https://data.unistats.ac.uk/api/KIS/Institutions.JSON?pageIndex=1&pageSize=25',
        'beforeSend': function(xhr) {
            xhr.setRequestHeader("Authorization",
                "Basic " + btoa("AAA"));
                console.error("Basic " + btoa("AAA"));
        },
        success: function(result) {
            alert('done');
        },
        error: function(jqXHR, status, error){ console.log(status, error); }
    });
}
);      </script>   
dc5
  • 12,341
  • 2
  • 35
  • 47
ThePerson
  • 3,048
  • 8
  • 43
  • 69
  • Check out the [documentation for `getJSON`](http://api.jquery.com/jquery.getjson/) – Andrew Whitaker Aug 16 '13 at 19:58
  • Have you checked in firebug console whether the request is actually going to server? Also check if your server side method accepts "get" type or "post" type request or both. – Faisal Mq Aug 16 '13 at 20:01
  • Are you loading your page off the file system or off of a local/remote http server? From the `null` Origin - looks like you are loading off the file system. Try loading off an http server. – dc5 Aug 16 '13 at 20:42
  • See this post about null origin: [XmlHttpRequest error: Origin null is not allowed by Access-Control-Allow-Origin](http://stackoverflow.com/questions/3595515/xmlhttprequest-error-origin-null-is-not-allowed-by-access-control-allow-origin) – dc5 Aug 16 '13 at 20:46
  • @NutterzUK - see my above two comments. If you can, post the response headers you are getting back from the server. That should tell us more. – dc5 Aug 16 '13 at 20:53
  • Hi dc5. I've just tried both a domain I have and locally (I was just doing it locally), and they both show problems. I'll post the headers in the question below the rest. Thanks! – ThePerson Aug 16 '13 at 20:59
  • @dc5 this is the domain I have been using to test just now: http://spindroid.co.uk/tt/byUniversity.html – ThePerson Aug 16 '13 at 21:10
  • That is telling you that you can't issue an `OPTIONS` request as @Guffa surmised below. Do you have control over the server's CORS configuration? If you, you need to add `OPTIONS` as an allowed method. – dc5 Aug 16 '13 at 21:14
  • Hmm - never mind that comment. I believe the problem is still with your `Origin` header. I issued a request against the test server you posted using a rest client and get this back: `Allow: GET,HEAD,POST,OPTIONS ` – dc5 Aug 16 '13 at 21:19
  • I don't have access to anything on the server, it's an API ran by the UK government: http://unistats.direct.gov.uk/open-access-data/ – ThePerson Aug 16 '13 at 21:19
  • 1
    let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/35626/discussion-between-dc5-and-nutterzuk) – dc5 Aug 16 '13 at 21:20
  • you might try adding these options: `username: 'name', password: 'pass',` to the ajax object instead of the beforesend – Mark Schultheiss Aug 16 '13 at 21:26
  • 1
    This post gives a server side curl answer for php: http://stackoverflow.com/questions/11946307/jquery-ajax-cross-domain-with-basic-authentication – Mark Schultheiss Aug 17 '13 at 00:46
  • Thanks Mark. I'll give this a try. It seems like it will increase loading times but is a good solution. I'll let you know how it goes. – ThePerson Aug 17 '13 at 12:10

1 Answers1

7

The getJSON method doesn't take an object with settings. Use the ajax method instead, and specify dataType: 'json' as one of the settings.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • I suppose you could use `$.ajaxSetup()` and then call `$.getJSON()`. – Barmar Aug 16 '13 at 19:59
  • 1
    @Barmar: Yes, that is also an option. However, that affects all ajax calls, not just this one. – Guffa Aug 16 '13 at 20:01
  • Thanks, I've given this a go and I seem to be further than I was. Unfortunately, now I get the error condition alert('no'). Is there a good way to debug that? – ThePerson Aug 16 '13 at 20:05
  • @NutterzUK: Yes, by `console.log`ging the arguments passed to `error`, not just alerting `"no"`. Like this: `error: function(jqXHR, status, error){ console.log(status, error); }` – gen_Eric Aug 16 '13 at 20:15
  • Thanks, I get "errorNo Transport". As Faisal mq asked if I have tried using firebug. I just did, and I see an error 405 - Method not allowed. I've added the headers shown in the firebug request to the question. – ThePerson Aug 16 '13 at 20:19
  • Ahah! I found the solution I believe. I looked for the "errorNoTransport" issue which I was seeing and found this. http://stackoverflow.com/questions/5241088/jquery-call-to-webservice-returns-no-transport-error After adding: jQuery.support.cors = true; It seems to be working. – ThePerson Aug 16 '13 at 20:25
  • Oh, actually forget that. It said "done" once. I tried in firefox and I still get there error 405. – ThePerson Aug 16 '13 at 20:27
  • @NutterzUK: For some reason you are making an OPTIONS request instead of a regular GET or POST request. Add a setting like `type: 'GET'` to the options. – Guffa Aug 16 '13 at 20:32
  • @Guffa - if the request if going off do a different domain, the browser will request options first to see if CORS is allowed. – dc5 Aug 16 '13 at 20:34
  • @dc5: I see. Then the target server has to be configured to allow it, as it's not accepting the OPTIONS method at all right now. – Guffa Aug 16 '13 at 20:40
  • Yes, it is sending an "options" request, I can see that in firebug. Well observed (I hadn't seen). I tried adding type: 'GET' and that didn't seem to work, I already had it but in lowercase (I changed it to uppercase). I then found this article: http://stackoverflow.com/questions/5241088/jquery-call-to-webservice-returns-no-transport-error I changed dataType = json to dataType = jsonp and now it works, but I'm not sure why. – ThePerson Aug 16 '13 at 20:41
  • I'll add my working code to the question so it can be formatted properly and viewed for nay suggestions as to what exactly happened. – ThePerson Aug 16 '13 at 20:43
  • @NutterzUK: JSONP is used for cross domain calls. It actually uses a `script` tag to do the request instead of a regular AJAX call. As a script can be loaded from a different domain, it doesn't have the same restrictions as AJAX calls. The response from a JSONP call is JSON wrapped in a function call. – Guffa Aug 16 '13 at 20:44
  • Thanks for all your help. Sorry about this, what I thought worked... doesn't (again). It does return a response, but the response is: "Username and password needed". This means that the headers didn't add, and as I look into this a little further, it doesn't seem possible with jsonp. – ThePerson Aug 16 '13 at 20:50
  • @NutterzUK That seems correct: http://stackoverflow.com/questions/3350778/modify-http-headers-for-a-jsonp-request **and** http://stackoverflow.com/questions/3073287/set-headers-with-jquery-ajax-and-jsonp – Ian Aug 17 '13 at 03:55
  • @NutterzUK: Yes, that's right. As the JSONP call doesn't use the xhr object, adding a header to the xhr object has no effect. – Guffa Aug 17 '13 at 05:30