【问题标题】:How to serve multiple domains which share the application back-end in Flask?如何在 Flask 中为共享应用程序后端的多个域提供服务?
【发布时间】:2018-01-27 18:53:29
【问题描述】:

我有两个网络域,分别称为 alpha.com 和 beta.com。我想在这两个不同的域上运行两个不同的面向公众的网站,但是来自共享服务器并在同一个烧瓶应用程序和应用程序上下文中。这些网站都将共享后端应用程序和数据库,

我目前的项目结构如下:

app/
  -static/
    --alphacom_static/
    --betacom_static/
    --shared_backend_static/
  -blueprints/
    --alphacom_frontend_bluprint/
    --betacom_frontend_blueprint/
    --shared_backend_blueprint/

我通过服务器上的反向代理为在本地主机上运行的 beta.com 提供烧瓶/gevent。我打算为 alpha.com 添加一个蓝图。

beta.com 登陆页面的路由是@blueprint.route(r'/', methods=['GET', 'POST'])。当用户在 beta.com/login 登录时,他们会被定向到 beta.com/app。

使用蓝图和路由的方法是什么,将 alpha.com 作为蓝图并在用户登录时为它们提供 alpha.com/app?

如何修改 alpha.com 的路由以避免与 beta.com 发生冲突?

【问题讨论】:

    标签: python flask web-applications


    【解决方案1】:

    我发现它在烧瓶当前的稳定版本Flask==0.12.2 中没有得到很好的支持。理论上可以通过host_matching 完成。但在我的测试中,静态路由总是被破坏。

    但是,在撰写本文时,master 上的烧瓶开发版本已经合并了一个拉取请求,使其更容易一些。执行pip install git+git://github.com/pallets/flask.git 将安装Flask==0.13.dev0。然后,使用工厂模式创建烧瓶应用程序,您可以在我的情况下设置host_matching=Truestatic_host=127.0.0.1:8000

    对我来说,我的工厂函数如下所示:

    def create_app(config_obj=None):
        """An application factory, as explained here:
        http://flask.pocoo.org/docs/patterns/appfactories/.
        :param config_object: The configuration object to use.
        """
        app = Flask(__name__, host_matching=True, static_host='127.0.0.1:8000')
        app.config.from_object(config_obj)
        register_extensions(app)
        register_blueprints(app)
        return app
    

    完成这项工作所需的另一件事是修改您的主机并设置您希望在主机文件中引用的域。在 Windows 上,可以在 C:\Windows\System32\drivers\etc\hosts 找到。在 hosts 文件的底部,我做了如下修改:

    # localhost name resolution is handled within DNS itself.
    #   127.0.0.1       localhost
    #   ::1             localhost
        127.0.0.1       alpha.local
        127.0.0.1       beta.local
        127.0.0.1       local
    

    您需要在反向代理(Linux 上的 NGINX 或 Windows 上的 IIS)后面运行此解决方案,并将其设置为将适当的请求转发到 alpha.local:8000beta.local:8000 在本示例的情况下。但是,您将根据您的实际需要修改<subdomain>.local:<port>

    您将处理的另一个问题是浏览器抱怨 CORS 请求,因此您可能需要为 Access-Control-Allow-Origin: * 或特定域(如 Access-Control-Allow-Origin: http://beta.local:8000)设置标头。对于开发服务器,我发现这有助于 CORS 允许字体访问:

    @blueprint.after_app_request
    def add_headers_to_fontawesome_static_files(response):
        """
        Fix for font-awesome files: after Flask static send_file() does its
        thing, but before the response is sent, add an
        Access-Control-Allow-Origin: *
        HTTP header to the response (otherwise browsers complain).
        """
        if not os.environ.get('APP_ENV') == 'prod':
            if request.path and re.search(r'\.(ttf|woff|woff2|svg|eot)$', request.path):
                response.headers.add('Access-Control-Allow-Origin', '*')
            return response
    

    请注意,对于生产,您必须在代理(如 NGINX 或 IIS)上设置修改后的标头,上述功能对生产没有用。

    最后,host_matching=True 必须为主机指定路由,示例如下:

    @blueprint.route('/about/', methods=['GET', 'POST'],
                     host='<string:subdom>.local:8000')
    def about_app(**kwargs):
        """The about page."""
        return render_template('about.html')
    

    如果您执行上述路由,则在应用程序某处的函数中设置 url_defualts 会很有帮助,如下所示:

    @blueprint.app_url_defaults
    def add_subdom(endpoint, values):
        path = request.url_root
        if 'alpha.local' in path:
            g.subdom = 'alpha'
        elif 'beta.local' in path:
            g.subdom = 'beta'
        if current_app.url_map.is_endpoint_expecting(endpoint, 'subdom'):
            values['subdom'] = g.subdom
    

    祝你好运,这并不容易。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-07-13
      • 2020-08-28
      • 2017-08-30
      • 2018-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多