我正在运行nginx + gunicorn + flask
我的nginx配置如下:
...
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header Stage "development";
proxy_redirect off;
...
我的烧瓶应用程序如下:
from flask import Flask, request
from werkzeug.contrib.fixers import ProxyFix
app = Flask(__name__)
# configuration settings
if request.headers.get('Stage') == 'production':
app.config.from_object('config.production_config')
else:
app.config.from_object('config.development_config')
@app.route('/')
def index():
return "hello"
app.wsgi_app = ProxyFix(app.wsgi_app)
然而,
这似乎不起作用。
我得到一个:RuntimeError:在请求上下文之外工作
设置了我的nginx,以便我可以拥有开发/生产环境,但我希望能够说这个“服务器位置”是一个开发环境,我希望Flask使用适当的配置。
答案 0 :(得分:4)
应用程序配置适用于整个应用程序,而请求标头仅适用于一个请求。相同的应用程序通常处理许多请求。因此,您无法根据请求标头设置配置。
当没有请求到达应用程序时,模块级别的代码在服务器启动时执行,因此没有当前请求。这就是“在请求上下文之外工作”消息的含义。
您尝试做的事情(prod vs. dev config)最好在启动gunicorn服务器的脚本中使用环境变量。如果你想要两个同时最简单的就是运行两个gunicorn服务器。
或者,创建两个应用程序对象,在同一个进程中运行它们,并使用与以下类似的WSGI中间件进行调度:http://flask.pocoo.org/docs/patterns/appdispatch/
答案 1 :(得分:1)
这有点旧,但我想补充一下我们如何用烧瓶完成这项工作。其中大部分改编自http://flask.pocoo.org/docs/config/。
在我们的config.py中,我们定义了多个类(每个环境一个):
class Config(object):
FOO = 1
BAR = 2
class Development(Config):
BAR = 3
然后在我们的每个应用程序节点中,我们在gunicorn init脚本中设置了一个环境变量(对于我们来说,它存在于一个超级用户配置中但不一定是这样)。
APPLICATION_ENV='Development'
然后在初始化期间烧瓶应用程序内(仅在服务器启动时运行,而不是在请求上下文中运行):
try:
env = os.environ['APPLICATION_ENV']
except KeyError as e:
logging.error('Unknown environment key, defaulting to Development')
env = 'Development'
app.config.from_object('config.%s' % env)
现在app.config ['BAR']将是3.
我们还希望支持本地配置文件(例如,在开发人员计算机上或从厨师直接部署到机器而不存储在git中的密码)。为此,我们对上述内容进行了扩展,以便根据app.config ['LOCAL_CONFIG']参数加载本地配置。
class Development(Config):
BAR = 3
LOCAL_CONFIG = '/etc/localConfig.py'
然后在/etc/localConfig.py
BAR = 4
在上面的代码加载环境的初始app.config之后,再次在我们的应用初始化代码中:
if 'LOCAL_CONFIG' in app.config:
#try to load the local configuration overrides
if app.config.from_pyfile(app.config['LOCAL_CONFIG'], silent=True):
logging.info('Loaded local config file at %s' % app.config['LOCAL_CONFIG'])
else:
logging.warning('Failed to load local config file at %s - does it exist?' % app.config['LOCAL_CONFIG'])
此时app.config ['BAR']为4.
这并不完美,因为如果你的配置中有dicts,你将只能覆盖整个dict,而不是覆盖整个dict。它确实完成了我们所需要的大部分工作。