10

这会很长:

好的,所以我正在开发一个谷歌日历小工具,它将请求发送到托管在 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 请求,但是我找不到解释这一切的示例。

请帮忙。

4

3 回答 3

22

好的,我修好了。

首先,我在这里意识到标头是由服务器发送的,所以在 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");
    }
});  

在网络服务中:

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'
于 2013-09-12T13:24:13.253 回答
2

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

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

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

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

如果你需要一个轻量级的解决方案,这一切都可以用 POJS(plain-old-JavaScript)来完成,而不需要求助于 jQuery。只需连接 IE8+ 的 window.XDomainRequest 和其他浏览器的 window.XMLHttpRequest 即可。

于 2014-02-23T03:28:17.997 回答
2

可以使用调度方法更简单

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
于 2017-07-03T06:53:45.873 回答