Flask - Невозможно переопределить субдомен по умолчанию для чертежей, которым нужен другой субдомен - PullRequest
1 голос
/ 30 мая 2020

У меня есть проект / приложение 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, предполагающей переопределить его позже, и просто явной настройкой поддоменов вручную.

Есть идеи, что здесь происходит?

Бонусные баллы : какой из них является предпочтительным способом установки поддомена? Я видел, как это делалось в обоих направлениях.

app.register_blueprint(apibp, subdomain='api')

против

apibp = Blueprint('api', 'api', subdomain='api')
app.register_blueprint(apibp)

1 Ответ

2 голосов
/ 08 июня 2020

Чего не хватает, так это опции subdomain_matching для Flask():

subdomain_matching - учитывайте поддомен относительно SERVER_NAME при сопоставлении маршрутов . По умолчанию - False.

Так как app - это относительное имя, вам нужно установить его на True:

app = Flask(__name__, subdomain_matching=True)

Раньше это делалось неявно, но как of Flask 1.0 это явный переключатель. Изменение было внесено, потому что разные люди по-разному относились к значению параметра SERVER_NAME, см. Flask issue # 998 .

Что касается того, где вы устанавливаете параметр subdomain, это твой выбор. Если вы повторно используете чертежи в разных контекстах, то имеет смысл установить параметр поддомена в вызове app.register_blueprint(), тогда как установка его в вызове экземпляра Blueprint() может сделать его более самодокументированным, если вы создаете этот объект чертежа ближе к вашим маршрутам и поэтому хотим прояснить для кого-то, кто работает над этим кодом, что они влияют только на определенный субдомен c.

...