我有一个Flask项目/应用程序,希望主要从app.example.com
提供该服务。我在此应用程序中还有一个蓝图,只能从api.example.com
提供。
[现在,如果我将app
设置为默认子域,则无法在应从其他子域提供服务的其他蓝图中覆盖此默认设置(例如api
)。实际上,使用不同子域创建的任何蓝图都将在404。
换句话说,下面的代码不起作用(api.example.com/test2
将为404):
# -*- coding: utf-8 -*-
from flask import Flask, Blueprint
app = Flask(__name__)
app.config['SERVER_NAME'] = 'example.com'
app.url_map.default_subdomain = 'app' # set default subdomain, intending to override it below for `api.*`
appbp = Blueprint('app', 'app')
apibp = Blueprint('api', 'api')
@appbp.route('/test1')
def app_hello():
# this works (app.example.com/test1)
return 'appbp.app_hello'
@apibp.route('/test2')
def api_hello():
# this will 404 (api.example.com/test2)
return 'apibp.api_hello'
app.register_blueprint(appbp) # this works, serves from `app.example.com`
app.register_blueprint(apibp, subdomain='api') # doesn't work, `api.example.com/test2` will 404, so will `app.example.com/test2` (tried just in case it was using the default subdomain instead)
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8888, debug=True)
但是,如果我每次注册蓝图时都没有设置默认子域,而相反设置了子域,则它对于app
和api
都可以神奇地工作:
# -*- coding: utf-8 -*-
from flask import Flask, Blueprint
app = Flask(__name__)
app.config['SERVER_NAME'] = 'example.com'
# app.url_map.default_subdomain = 'app' # now try without a default
appbp = Blueprint('app', 'app')
apibp = Blueprint('api', 'api')
@appbp.route('/test1')
def app_hello():
# this works (app.example.com/test1)
return 'appbp.app_hello'
@apibp.route('/test2')
def api_hello():
# this works (api.example.com/test2)
return 'apibp.api_hello'
app.register_blueprint(appbp, subdomain='app') # works, explicitly set subdomain on each blueprint
app.register_blueprint(apibp, subdomain='api') # works, explicitly set subdomain on each blueprint
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8888, debug=True)
在两个示例中,似乎蓝图都已在正确的子域中注册:
<Rule 'app|/test1' (OPTIONS, GET, HEAD) -> app.app_hello>
<Rule 'api|/test2' (OPTIONS, GET, HEAD) -> api.api_hello>
但是,很明显,设置app.url_map.default_subdomain
打算稍后覆盖它和仅手动显式设置子域之间是有区别的。
你知道这是怎么回事吗?
Bonus points:设置子域的首选方法是哪一种?我已经看过了两种方法。
app.register_blueprint(apibp, subdomain='api')
vs。
apibp = Blueprint('api', 'api', subdomain='api')
app.register_blueprint(apibp)
缺少的是subdomain_matching
option for Flask()
:
subdomain_matching –匹配路由时考虑相对于
subdomain_matching
的子域。默认为False。
由于Flask()
是相对名称,您需要将其设置为SERVER_NAME
:
app
这以前是隐式完成的,但是从Flask 1.0开始,这是一个明确的开关。之所以做出更改,是因为不同的人对True
的设置有不同的期望,请参阅app = Flask(__name__, subdomain_matching=True)
。
关于设置SERVER_NAME
选项的位置,这是您的选择。如果要在不同的上下文中重用蓝图,那么在Flask issue #998调用中设置subdomain选项更有意义,而在subdomain
实例调用中进行设置可能会使其更具自说明性(如果您正在创建该蓝图对象)更接近您的路线,因此希望让从事该代码工作的人员更清楚地知道他们仅影响特定的子域。