This is going to be long:
Ok so I'm developing a google calendar gadget which sends requests to a Python webapp2 REST api hosted on Google App Engine.
The problem comes when I try to POST something it doesn't allows me because of CORS. In Chromes' DevTools it 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'm aware that this is because of CORS. Here:
Ajax - 'Origin localhost is not allowed by Access-Control-Allow-Origin'
It says that I have to add
Access-Control-Allow-Origin: *
To the headers, but then again I'm new to ajax and I wonder if it's done this way:
$.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 this headers the output is different (which makes me wonder if the origin has been allowed, though I don't really 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've even found this:
http://james.padolsey.com/javascript/cross-domain-requests-with-jquery/
Which lets me do GET requests, but I'd like to learn how to do them without this.
Also on my webserver I have this:
...
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 don't know if I must add something more to the webserver, nor I've found info saying that I have to. Also I think I'm near to achieve the CORS request but, I can't find THE Example that explains it all.
Please help.
Ok I fixed it.
First of all I realized here that the headers were sent by the server so I was doing wrong when sending those headers in the AJAX request.
Finally, after searching around the worldwide web I found what I was missing. It was something stupid. I found the page that fixed it all:
http://enable-cors.org/server_appengine.html
So finally everything 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 webService:
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'
I just want to point out a detail that might help others:
Browsers differ in how they handle the "Access-Control-Allow-Orgin" header. For example, I found that Chrome blocks cross domain posts when the header value is a wildcard (*) as in the solution code above. It considers it too liberal and wants a specific origin. Yet, other browsers such as IE and FireFox did not care.
So if you want to build a cross browser solution it would be best set the value of "Access-Control-Allow-Origin" to the Origin value sent with the request.
If you're using SSL then you'll encounter some other differences that will need to be tested as well.
And if you need a lightweight solution this can all be done with POJS (plain-old-JavaScript) without resorting to jQuery. Just wire up the window.XDomainRequest for IE8+ and the window.XMLHttpRequest for other browsers and you're in business.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With