Flask配置应用时出现404错误,请求排查原因
Flask加载配置后出现404错误的排查与解决
我遇到了一个奇怪的Flask问题:当移除app.py里加载配置的两行代码时,访问127.0.0.1:8000能正常返回"hey",但保留配置语句就出现404错误。先把我的项目情况贴出来:
项目目录结构
. ├── app.py ├── config/ │ ├── __init__.py │ └── settings.py └── instance/ ├── __init__.py └── settings.py
代码详情
app.py
from flask import Flask from flask_debugtoolbar import DebugToolbarExtension from flask_mail import Mail from flask_wtf.csrf import CsrfProtect app = Flask(__name__) debug_toolbar = DebugToolbarExtension() mail = Mail() csrf = CsrfProtect() # 关键就是这两行:注释掉正常,保留就404 app.config.from_object('config.settings') app.config.from_pyfile('settings.py', silent=True) @app.route('/') def hello_world(): return "hey" debug_toolbar.init_app(app) mail.init_app(app) csrf.init_app(app) app.run(port=8000)
两个settings.py的代码
config/settings.py和instance/settings.py内容完全一致:
DEBUG = False SERVER_NAME = 'localhost:8000' SECRET_KEY = 'insecurekeyfordev' # Flask-Mail. MAIL_DEFAULT_SENDER = 'contact@local.host' MAIL_SERVER = 'smtp.gmail.com' MAIL_PORT = 587 MAIL_USE_TLS = True MAIL_USE_SSL = False MAIL_USERNAME = 'you@gmail.com' MAIL_PASSWORD = 'awesomepassword' # Celery. CELERY_BROKER_URL = 'redis://:devpassword@redis:6379/0' CELERY_RESULT_BACKEND = 'redis://:devpassword@redis:6379/0' CELERY_ACCEPT_CONTENT = ['json'] CELERY_TASK_SERIALIZER = 'json' CELERY_RESULT_SERIALIZER = 'json' CELERY_REDIS_MAX_CONNECTIONS = 5
问题原因分析
问题出在SERVER_NAME这个配置项上!
当你设置了SERVER_NAME = 'localhost:8000',Flask会启用严格的Host头匹配规则:
- 所有请求的Host必须严格等于这个值,否则Flask会认为请求的是其他站点,不会匹配你的路由。
- 你访问的是
127.0.0.1:8000,此时请求的Host是127.0.0.1:8000,和配置里的localhost:8000不匹配,所以Flask找不到对应的路由,直接返回404。
而当你注释掉配置加载代码时,SERVER_NAME没有被设置,Flask会跳过这个严格匹配,所以127.0.0.1:8000的请求能正常命中根路由。
解决方案
有几种简单的解决方式,选适合你的就行:
修改访问地址:直接用
localhost:8000代替127.0.0.1:8000访问,这样Host头和配置的SERVER_NAME完全匹配,就能正常返回内容。调整配置:
- 把
SERVER_NAME改成'127.0.0.1:8000',和你实际访问的地址一致; - 或者直接删除
SERVER_NAME配置项——如果你的项目不需要子域名路由、生成带域名的绝对URL这类功能,完全不需要设置这个参数,反而能避免这类匹配问题。
- 把
兼容多Host(进阶):如果确实需要保留
SERVER_NAME同时兼容localhost和127.0.0.1,可以自定义Flask的路由匹配规则,或者设置APPLICATION_ROOT,不过这种情况比较少见,前面两种方案足够解决大部分场景。
内容的提问来源于stack exchange,提问作者gambit2017
相关产品推荐
相关产品推荐

