首页 > 解决方案 > 使用 nginx 烧瓶“redirect(url_for)”和“@login_required”错误

问题描述

我制作了一个托管在我的树莓派上的网络应用程序,我正试图从互联网上访问它。我正在使用 Dataplicity ( https://docs.dataplicity.com/docs/host-a-website-from-your-pi ) 使用 nginx 访问我的服务器。

在本地,一切正常。我会启动应用程序

flask run --host=0.0.0.0 --port=8000

使用端口 8000 或 80 在浏览器中转到我的 pi 地址,并成功获取我的应用程序的主页。在此之前,该过程同样适用于 dataplicity。

当我调用 redirect(url_for) 函数(包括@login_required)时,问题就出现了。一旦我通过 dataplicity 调用它,我就会得到“503 服务暂时不可用”。

当我在本地工作时(或在外部使用端口转发 -> 这让我认为问题出在 Dataplicity 和 nginx 上),当我尝试访问我的 /camera 视图功能而不先登录到应用程序时,我看到以下 GET 请求:

127.0.0.1 - - [07/May/2019 22:27:47] "GET /camera HTTP/1.0" 302 -
127.0.0.1 - - [07/May/2019 22:27:47] "GET /login?next=%2Fcamera HTTP/1.0" 200 -

当我尝试通过 dataplicity 访问它时,我只得到:

127.0.0.1 - - [07/May/2019 22:28:37] "GET /camera HTTP/1.0" 302 -

: "GET /login?next=%2Fcamera HTTP/1.0" 200 - 不存在。

如果这有帮助,dataplicity 中的每个 url 都显示为 https,除非我点击了 redirect(url_for) 或 @login_requested 函数,否则它会变成 http。

我尝试了在 Stack Overflow 上找到的几种不同的 nginx 配置,还尝试通过阅读文档对它们进行一些调整。这是徒劳的。我不会分享它们,因为我尝试的所有变化都导致相同的效果。

这是我的实际 nginx 配置:

server {
        listen 80 ;
        server_name _;
        access_log /var/log/app_access.log;
        error_log /var/log/app_error.log;
        location / {
            proxy_pass http://localhost:8000;
            proxy_redirect off;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
}

这是我的应用程序中的重要代码:

@app.route("/")
def index():
    return render_template('index.html', title='Cat')

@app.route('/login', methods=['GET', 'POST'])
def login():
    if current_user.is_authenticated:
        return redirect(url_for('index'))
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user is None or not user.check_password(form.password.data):
            flash('Invalid username or password')
            return redirect(url_for('login'))
        login_user(user, remember=form.remember_me.data)
        next_page = request.args.get('next')
        if not next_page or url_parse(next_page).netloc != '':
            next_page = url_for('index')
        return redirect(next_page)
    return render_template('login.html', title='Sign In', form=form)

@app.route("/camera")
@login_required
def stream():
    templateData = {
        'title' : "Stream"
    }
    return render_template('camera.html', **templateData)

我希望在外部获得与本地获得相同的体验(通过 dataplicity,因为我不喜欢打开端口的想法)。也就是说,每次我被重定向时都能够使用我的“登录”视图功能而不会遇到错误。

更新:

我的应用程序终于可以正常运行了。我认为答案是 Gunicorn。我有以下supervisor文件,我几乎没有测试过,因为我没有从中得到任何明确的反馈:

[program:app]
command=/var/www/html/app/sandbox/bin/gunicorn -b localhost:8000 -w 4 ...
directory=/var/www/html/app/
user=pi
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true

今天试了很多次,重新加载的时候app就可以正常使用了supervisorctl。我仍然需要找出是什么让这个特定的 nginx 配置只在 Gunicorn 运行时才起作用。

flask run --host=0.0.0.0 --port=8000仍然无法正常工作。

gunicorn -b 0.0.0.0:8000 -w 4 app:app正在工作中。

标签: pythonnginxflaskraspberry-piwebserver

解决方案


推荐阅读