8

我在终止 SSL 的负载平衡后面有一个 Flask 应用程序。我有在使用 SSL 时“检测”并改变请求对象的代码:

@app.before_request
def before_request():
    x_forwarded_proto = request.headers.get('X-Forwarded-Proto')
    if  x_forwarded_proto == 'https':
        request.url = request.url.replace('http://', 'https://')
        request.url_root = request.url_root.replace('http://', 'https://')
        request.host_url = request.host_url.replace('http://', 'https://')

然后我有一个蓝图视图功能:

admin = Blueprint('admin', __name__, url_prefix='/admin')
@admin.route('/login')
def login():
    print request.url

这个函数的输出是(当我去 /admin/login 时)总是 http:// 而不是 https:// (即使它应该在before_request函数中发生了变异。

关于如何解决这个问题的任何想法?

4

1 回答 1

10

原来request是一个代理对象。我不确定内部结构,但每次导入都会“重置”。我通过子类化解决了这个问题Request

class ProxiedRequest(Request):
    def __init__(self, environ, populate_request=True, shallow=False):
        super(Request, self).__init__(environ, populate_request, shallow)
        # Support SSL termination. Mutate the host_url within Flask to use https://
        # if the SSL was terminated.
        x_forwarded_proto = self.headers.get('X-Forwarded-Proto')
        if  x_forwarded_proto == 'https':
            self.url = self.url.replace('http://', 'https://')
            self.host_url = self.host_url.replace('http://', 'https://')
            self.base_url = self.base_url.replace('http://', 'https://')
            self.url_root = self.url_root.replace('http://', 'https://')

app = Flask(__name__);
app.request_class = ProxiedRequest
于 2013-11-07T17:25:45.357 回答