CORS – 使用AJAX在Python(webapp2)Web服务上发布

这将是漫长的:

好的,我正在开发一个谷歌日历小工具,它将请求发送到托管在Google App Engine上的Python webapp2 REST api。

当我尝试发布因CORS而不允许我发布的内容时,问题就来了。 在Chromes的DevTools中它说:

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. 

我知道这是因为CORS。 这里:

Ajax – Access-Control-Allow-Origin不允许使用Origin localhost

它说我必须添加

 Access-Control-Allow-Origin: * 

对于标题,但是我又是ajax的新手,我想知道它是否以这种方式完成:

  $.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"); } }); 

添加此标题的输出是不同的 (这让我想知道原点是否被允许,但我真的不知道):

 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. 

我甚至发现了这个:

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

这让我可以做GET请求,但是我想学习如何在没有这个的情况下完成它们。

同样在我的网络服务器上,我有这个:

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

我不知道是否必须向网络服务器添加更多内容,我也没有找到信息说我必须这样做。 此外,我认为我即将实现CORS请求,但是,我找不到解释这一切的示例。

请帮忙。

好的,我修好了。

首先,我在这里意识到标头是由服务器发送的,所以我在AJAX请求中发送这些标头时做错了。

最后,在搜索了全球网络后,我发现了我所缺少的内容。 这是愚蠢的事情。 我找到了修复它的页面:

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

所以最后一切看起来像这样:

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

并在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' 

我只是想指出一个可能对其他人有帮助的细节:

浏览器在处理“Access-Control-Allow-Orgin”标头方面有所不同。 例如,我发现当标头值为通配符(*)时Chrome会阻止跨域post,如上面的解决方案代码中所示。 它认为它过于自由,想要一个特定的起源。 然而,其他浏览器,如IE和FireFox并不关心。

因此,如果要构建跨浏览器解决方案,最好将“Access-Control-Allow-Origin”的值设置为随请求一起发送的Origin值。

如果您正在使用SSL,那么您将遇到一些其他需要测试的差异。

如果你需要一个轻量级的解决方案,这可以用POJS(普通的JavaScript)完成,而不需要使用jQuery。 只需连接IE8 +的window.XDomainRequest和其他浏览器的window.XMLHttpRequest即可开展业务。

用调度方法可以更简单

 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