kanch.blog

posted at 2016-12-06 10:32:35 +0000

Python Flask Google App Engine允许Access-Control-Allow-Origin跨域访问

最近在做一个纯API接口,部署到Google App Engine上面(为了利用GAE的负载均衡,减少服务器压力)。

最后在另外一台服务器上调用的时候,却无法正确获取数据,提示错误如下:

**XMLHttpRequest cannot load ‘'. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '' is therefore not allowed access.**

经过搜索发现是因为跨域调用问题(即从一个域名请求另外一个域名下的信息,至少在Chrome中是禁止的)

解决该问题的方法如错误提示信息所示,在服务器端的response加入Access-Control-Allow-Origin即可。

网上查出来的很多方法都是通过在GAE的app.yaml文件里面添加来实现的,后面我尝试后发现不管用。

于是经过一番搜索,搜索出了这个:Decorator for the HTTP Access Control

为Flask写一个访问修饰器,然后,通过在要控制Access-Control的路由函数前面添加@crossdomain(origin=’*‘)来实现发送Access-Control-Allow-Origin头。

首先,我们定义一个如下函数(这个函数内部还有函数哦):

from datetime import timedelta from flask import make_response, request, current_app from functools import update_wrapper

def crossdomain(origin=None, methods=None, headers=None, max_age=21600, attach_to_all=True, automatic_options=True): if methods is not None: methods = ‘, ‘.join(sorted(x.upper() for x in methods)) if headers is not None and not isinstance(headers, basestring): headers = ‘, ‘.join(x.upper() for x in headers) if not isinstance(origin, basestring): origin = ‘, ‘.join(origin) if isinstance(max_age, timedelta): max_age = max_age.total_seconds()

def get_methods():
    if methods is not None:
        return methods

    options_resp = current_app.make_default_options_response()
    return options_resp.headers['allow']

def decorator(f):
    def wrapped_function(*args, **kwargs):
        if automatic_options and request.method == 'OPTIONS':
            resp = current_app.make_default_options_response()
        else:
            resp = make_response(f(*args, **kwargs))
        if not attach_to_all and request.method != 'OPTIONS':
            return resp

        h = resp.headers

        h['Access-Control-Allow-Origin'] = origin
        h['Access-Control-Allow-Methods'] = get_methods()
        h['Access-Control-Max-Age'] = str(max_age)
        if headers is not None:
            h['Access-Control-Allow-Headers'] = headers
        return resp

    f.provide_automatic_options = False
    return update_wrapper(wrapped_function, f)
return decorator</pre>

接着,我们只需要在我们要加入Access-Control-Allow-Origin头的位置添加下面这一句即可:

#

@crossdomain(origin=’_’) # <-添加这句,可以把_改为想要允许的域名

@app.route(‘/my_service’) @crossdomain(origin=’*’) #这货的添加位置应该在路由之后 def my_service():

#do something</pre>

然后,我们再次调用API,就会发现,没有报这个错误了。



© kanchzl AT kanchz DOT com

last updated on 2019-08-20 07:01:05 +0000