如何在Flask中为多个共享应用程序后端的域提供服务?

时间:2017-08-19 04:21:28

标签: python flask web-applications

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

我目前的项目结构如下:

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

我通过服务器上的反向代理服务于使用flask / gevent在localhost上运行的beta.com。我打算为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发生冲突?

1 个答案:

答案 0 :(得分:2)

我发现它在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
祝你好运,这并不容易。