3

I am porting an application from Django to purely HTML5/CSS with AngularJS and am facing issues making JSON POST requests to TheTVDB REST API server (https://api.thetvdb.com/).

The API call is being done in a service on AngularJS:

return {
    login: function(){
        return $http({
            method: 'POST',
            dataType: 'json',
            headers: {'Content-Type': 'application/json'},
            data: {'apikey':apiKey, 'username': username, 'userkey': identifier},
            url: tvdbAuthURL
        })
    }
}

And then I get this error:

XMLHttpRequest cannot load https://api.thetvdb.com/login/. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8000' is therefore not allowed access. The response had HTTP status code 401.

I have tried avoiding pre-flighting the request but no luck and since I did not have this issue using python requests lib, for example, (I trigger request to the tvDB using this python lib from the same machine running the angular JS app with no problems at all) I wonder if there isn't a way or a different directive in AngularJS to keep it from setting CORS headers.

TheTVDB will not add CORS to their server as most of their users are running Laravel (PHP), Java and Django(Python) applications and are using their services with no such CORS problems.

Your help is much appreciated.

Thank you, Best Regards TS

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
T.S.
  • 192
  • 2
  • 13
  • 1
    Create a proxy in python – charlietfl Jun 29 '16 at 01:39
  • I wanted to avoid that for architectural reasons. But does that mean that I am limited by AngularJS for when servers do not provide CORS support? – T.S. Jun 29 '16 at 01:43
  • No it means you are limited by browser security. You have no other choice other than use a third party proxy – charlietfl Jun 29 '16 at 01:44
  • your api receives data from the body? or via parameters?, also isn't reduntant use dataType with the headers? – Paulo Galdo Sandoval Jun 29 '16 at 01:47
  • @PauloGaldoSandoval I would receive a json back from the server with the token information for me to carry on with other requests. The dataType maybe redundant, but it is not of an impact here, I suppose. – T.S. Jun 29 '16 at 01:53
  • Some answers may be here: http://stackoverflow.com/questions/10636611/how-does-access-control-allow-origin-header-work Something else not suggested here other than proxy is to Embed the remote server in an iframe and communicate through fragment or window.name, check this out http://www.ibm.com/developerworks/library/wa-crossdomaincomm/#N10120 – applecrusher Jun 29 '16 at 01:56
  • @applecrusher thank you! I am very eager to try the iframe solution and see how that goes about! That is a very interesting work around and clean from my perspective and which to keep it a stand alone application with fewer dependencies as possible. I will give it a try and let you all know how that goes! – T.S. Jun 29 '16 at 02:05

3 Answers3

1

Your Python request works because it is coming from your server or local machine, and the same origin policy only applies inside a browser.

Your best answer is to use a server-side script. Have your client side POST request go to a controller or endpoint on your server, which then triggers the server script. Assuming there is some return data from the API, you'd add that to your server's response and then send it to the client.

Matt West
  • 1,376
  • 1
  • 12
  • 18
  • My python request is triggered from localhost, my machine, to https://api.thetvdb.com/, so not from the server. I have no access to the server whatsoever, so I would have to have a python layer sitting on the same side as my angularJs just to intermediate these requests, as per the other comments and suggestions on this thread which I would like to avoid as much as possible. – T.S. Jun 29 '16 at 01:55
  • Sorry, I guess my answer was a little muddled. In this case, when I say "the server" I mean your local machine, or anywhere you are hosting your backend code. The API would be the server you have no control over. That's assuming you ARE hosting backend code somewhere. If this program is client-only and the API isn't CORS compliant, you're boned on a POST action. – Matt West Jun 29 '16 at 01:58
1

You can have a look here: https://forums.thetvdb.com/viewtopic.php?t=9125

The TVdb doesn't provide any cors header, which means you can't access the API directly via Javascript. However, as @Matt West said, the cors policy only works in browsers. The quick solution: Create a python program as a proxy, which redirect all your AJAX request to TVdb.

Kroderia
  • 623
  • 4
  • 15
0

Use a JSONP request. That way you can dodge the CORS.

EDIT: sorry, you're using POST, this would only work for get requests.

You can create a proxy that receives the request and then makes a CURL POST. There is no server side 'CORS' so you will be ok.

André Senra
  • 1,875
  • 2
  • 11
  • 13
  • 1
    Can't just say use jsonp as if it's magic fix for all CORS. API has to support it – charlietfl Jun 29 '16 at 01:36
  • 1
    Actually I can't use JSONP as I am actually issuing a POST request and I understant JSONP is for GET only, right? – T.S. Jun 29 '16 at 01:38