【问题标题】:ExtJS, Flask and AJAX: cross-domain requestExtJS、Flask 和 AJAX:跨域请求
【发布时间】:2012-09-28 22:22:33
【问题描述】:

我正在使用 ExtJS(客户端)和 Flask(服务器)开发一个 RESTful 应用程序:客户端和服务器通过协议链接.

当我尝试向服务器发出 AJAX 请求时出现问题,如下所示:

Ext.Ajax.request ({
    url: 'http://localhost:5000/user/update/' + userId ,
    method: 'POST' ,
    xmlData: xmlUser ,
    disableCaching: false ,
    headers: {
        'Content-Type': 'application/xml'
    } ,
    success: function (res) {
        // something here
    } ,
    failure: function (res) {
        // something here
    }
});

通过上述请求,客户端正在尝试更新用户信息。 很遗憾,这是一个跨域请求 (details)。

服务器按如下方式处理该请求:

@app.route ("/user/update/<user_id>", methods=['GET', 'POST'])
def user_update (user_id):
  return user_id

我在浏览器控制台上看到的是OPTIONS 请求,而不是POST。 然后,我尝试在 80 端口上启动 Flask 应用程序,但显然是不可能的:

app.run (host="127.0.0.1", port=80)

总之,如果客户端不能执行任何 AJAX 请求,我不明白客户端如何与服务器交互。

我怎样才能解决这个问题?

【问题讨论】:

    标签: javascript python ajax extjs flask


    【解决方案1】:

    这是使用 Flask 进行 CORS 的出色装饰器。

    http://flask.pocoo.org/snippets/56/

    如果链接失效,这是后代的代码:

    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
    

    【讨论】:

    • 再想一想,这个答案更合适。
    【解决方案2】:

    【讨论】:

    • 这是唯一的方法吗?
    • 您还可以通过您的域将所有请求代理到外部域,或者您可以使用 JSONP,但这是只读的。
    • 其实我没有任何外部域:它只是从客户端到服务器的请求-响应,都在本地主机中。我不明白为什么 Flask 不能像 PHP 那样在 Internet 端口(80)上运行。事实上,使用 PHP,我可以轻松地执行 AJAX 请求,而不会出现跨域问题。这就是我做这个帖子的原因。
    • Flask 当然可以在 80 端口上运行。您可以使用app.run(port=80),或者更有效地使用 Gunicorn 和 Nginx 将您的请求路由到 Flask。
    • 外部域我的意思是“任何 subdomain.domain:port 组合”与 extjs 运行的不同。让烧瓶在 80 上运行可能是你最好的选择。
    【解决方案3】:

    Flask-CORS 模块使得执行跨域请求极其简单

    app = Flask(__name__)
    cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
    

    另见:https://pypi.python.org/pypi/Flask-Cors

    【讨论】:

      猜你喜欢
      • 2013-03-06
      • 1970-01-01
      • 1970-01-01
      • 2012-04-15
      • 2011-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多