CORS in App Engine application (python)

ajax, cors, cross-domain, google-app-engine, python

Solution

I found the solution!! It was so simple; i feel a little bit stupid... If you look at the code, you will see some decorators before some method handlers. That's the problem: Sometimes i send content to the browser trough the decorators. And this content has no Allow-Control-* headers. And this is the reason why sometimes it failed and sometimes not (it fails when the decorator replies)

I have configured the headers in all the decorators which send content and it works fine :-). Thanks to all for your help, really!!

Problem

I'm trying to do x-domain request between 2 applications in app engine. In one hand, i have my API and in the other hand i have my "client application". I have been reading so much about CORS; i think i know how it works, and here comes the problem: It doesn't work. Simple request works, but the problem comes when i try to do non-simple request (with credentials). I have this code to handle the headers and allow CORS: ``` try: _origin = self.request.headers['Origin'] except: _origin = "http://myapp" self.response.headers.add_header("Access-Control-Allow-Origin", _origin) self.response.headers.add_header("Access-Control-Allow-Methods", "GET, POST, OPTIONS") self.response.headers.add_header("Access-Control-Allow-Credentials", "true") self.response.headers.add_header("Access-Control-Allow-Headers", "origin, x-requested-with, content-type, accept") self.response.headers.add_header('Content-Type', 'application/json') self.response.out.write( json.dumps( _response ) ) ``` EDITED: I'm working with both applications under the same domain (http://app1.domain.com and http://app2.domain.com). As i cannot use wildcards for request with credentials transference, i detect the Origin and i set the Allow-Origin in each request for this domain. In my client app i have this code to make the http requests: ``` jQuery.extend( { postJSON: function ( _url, _data, _callback) { $.ajax({ cache: false, crossDomain: true, url: _url, data: _data, type: 'POST', dataType: 'json', xhrFields: { withCredentials: true }, headers : { "x-requested-with" : "XMLHttpRequest" }, success: _callback, error: function() { _msg = "<strong>Error: </strong> Error en la petición HTTP (nivel de protocolo)."; _error( _msg ); } }); } ``` }); In order to handle the request, i have these methods: ``` @decorators.notAllowed def get(self): pass @decorators.isNotLogged @decorators.language def post(self): common._responseJSON( self, CU._doLogin( self ) ) def options(self): common._responseJSON( self, CU._doLogin( self ) ) ``` This is the OPTIONS request and response: ``` Request URL:http://myapi/method Request Method:OPTIONS Status Code:200 OK Request Headers Accept:*/* Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3 Accept-Encoding:gzip,deflate,sdch Accept-Language:es-ES,es;q=0.8 Access-Control-Request-Headers:origin, x-requested-with, content-type, accept Access-Control-Request-Method:POST Connection:keep-alive Host:myapi Origin:http://myapp Referer:http://myapp/ User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11 Response Headersview source Access-Control-Allow-Credentials:true Access-Control-Allow-Headers:origin, x-requested-with, content-type, accept Access-Control-Allow-Methods:GET, POST, OPTIONS Access-Control-Allow-Origin:http://myapp Cache-Control:no-cache Content-Encoding:gzip Content-Length:114 Content-Type:application/json Content-Type:text/html; charset=utf-8 Date:Fri, 16 Nov 2012 11:31:40 GMT Server:Google Frontend Vary:Accept-Encoding ``` And this is the HTTP POST request: ``` Accept:application/json, text/javascript, */*; q=0.01 Content-Type:application/json; charset=UTF-8 Origin:http://myapp Referer:http://myapp User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11 x-requested-with:XMLHttpRequest ``` But when the browser tries to do the POST request, it fails: ``` XMLHttpRequest cannot load http://myapi/method/. Origin http://myapp is not allowed by Access-Control-Allow-Origin. ``` Any idea? I'm getting insane with this problem... What i have to do in the OPTIONS http request? Maybe i'm not handling it in right way... :-/ Thanks in advance.

Original source