CORS - Using AJAX to Publish to a Python Web Service (webapp2)

This will be long:

Ok, so I'm developing a Google Calendar gadget that sends requests to the Python webapp2 REST api hosted by the Google App Engine.

The problem arises when I try to ALMOST something that it does not allow me because of CORS. DevTools Chromes says:

Method: OPTIONS. Status: (failed) Request header field Content-Type is not allowed by Access-Control-Allow-Headers. Origin https://hq34i4geprnp5vci191ljfuhcoerscl4-a-calendar-opensocial.googleusercontent.com is not allowed by Access-Control-Allow-Origin. 

I know this is because of CORS. Here:

Ajax - "The origin of the local host is not allowed through Access-Control-Allow-Origin"

It says that I have to add

 Access-Control-Allow-Origin: * 

In the headers, but again, I'm new to ajax, and I wonder if that was the case:

  $.ajax({ type: "POST", url: "https://myapp.appspot.com/service", contentType: "application/json; charset=utf-8", data: data, beforeSend: function (request) { request.setRequestHeader("Access-Control-Allow-Origin", "*"); } success: function(data) { alert("AJAX done"); } }); 

Adding these headers: is different (which makes me wonder if the origin is allowed, although I really don't know):

 Method: OPTIONS. Status: (failed) Request header field Content-Type is not allowed by Access-Control-Allow-Headers. XMLHttpRequest cannot load https://myapp.appspot.com/service. Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers. 

I even found this:

http://james.padolsey.com/javascript/cross-domain-requests-with-jquery/

Which allows me to make GET requests, but I would like to know how to do it without it.

Also on my web server I have the following:

 ... class webService(webapp2.RequestHandler): options(self): self.response.write('options') post(self): self.response.write('post') application = webapp2.WSGIApplication([ ('/', MainPage), ('/service', webService) ], debug=True) 

I do not know if I should add anything else to the web server, and did not find the information I need. Also, I think I'm close to achieving a CORS request, but I cannot find an example that explains all this.

Please, help.

+8
jquery python google-app-engine cors webapp2
source share
3 answers

Ok, I fixed it.

First of all, I realized here that headers were sent by the server, so I was mistaken when sending these headers to an AJAX request.

Finally, after searching all over the world, I found what I was missing. It was something stupid. I found a page that fixed everything:

http://enable-cors.org/server_appengine.html

So, it looks like this:

 $.ajax({ type: "POST", url: "https://myapp.appspot.com/service", contentType: "application/json; charset=utf-8", data: data, success: function(data) { alert("AJAX done"); } }); 

And in the web service:

 class webService(webapp2.RequestHandler): def get(self): self.response.headers.add_header('Access-Control-Allow-Origin', '*') self.response.headers['Content-Type'] = 'application/json' # do something def post(self): self.response.headers.add_header('Access-Control-Allow-Origin', '*') self.response.headers['Content-Type'] = 'application/json' # do something def options(self): self.response.headers['Access-Control-Allow-Origin'] = '*' self.response.headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept' self.response.headers['Access-Control-Allow-Methods'] = 'POST, GET, PUT, DELETE' 
+19
source share

I just want to point out the details that may help others:

Browsers differ in how they handle the "Access-Control-Allow-Orgin" header. For example, I found that Chrome blocks cross-domain messages when the header value is a wildcard character (*), as in the solution code above. He considers it too liberal and wants a specific origin. However, other browsers like IE and FireFox don't care.

So, if you want to build a cross-browser solution, it is best to set the "Access-Control-Allow-Origin" value to the Origin value sent with the request.

If you use SSL, you will come across some other differences that should also be tested.

And if you need a lightweight solution, all this can be done using POJS (simple-JavaScript-JavaScript), without resorting to using jQuery. Just plug in the window. XDomainRequest for IE8 + and window.XMLHttpRequest for other browsers, and you're in business.

+2
source share

Could be easier with the dispatch method

 class BaseRequestHandler(webapp2.RequestHandler): def dispatch(self): self.response.headers.add_header('Access-Control-Allow-Origin', '*') self.response.headers.add_header('Access-Control-Allow-Headers', 'Content-Type') webapp2.RequestHandler.dispatch(self) class LoginHandler(BaseRequestHandler): def login(self): #code here 
+1
source share

All Articles