Issue
I have a server running nginx. I'm trying to set up a Flask application at a specific sub-URL (e.g. http://server/app/
maps to Flask application's /
). If it matters, ultimately I intend for multiple Flask applications to run at various other sub-URLs on this same server.
I'm new to all of this so I've been running through tutorials, in particular I've followed these guides / posts:
- Flask + Gunicorn + Nginx Guide
- Flask docs re: nginx
- Flask docs re: ProxyFix
- https://stackoverflow.com/a/75123044
I have a section in my nginx sites-available/default file like this:
location /firmware {
proxy_pass http://localhost:6001;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Prefix /firmware;
}
It seems to be working fine (the Flask app is on 6001):
I've confirmed that requests to
/firmware
are forwarded to the Flask app.I've confirmed that the HTTP headers are present in the request and that they all contain the expected values:
X-Forwarded-For: 192.168.98.113 X-Forwarded-Proto: http X-Forwarded-Host: 192.168.99.223 X-Forwarded-Prefix: /firmware
Also, I'm using ProxyFix
in the Flask app to let the app know it's behind a proxy. I've got this bit of code when creating the application:
from flask import Flask
from werkzeug.middleware.proxy_fix import ProxyFix
app = Flask(__name__)
app.wsgi_app = ProxyFix(
app.wsgi_app,
x_for=1,
x_proto=1,
x_host=1,
x_prefix=1
)
@app.route("/")
def ... ():
...
However, the Flask application still sees the request as /firmware/
, rather than /
. I've verified this by checking the output logs when running the app via flask
, and also by adding a route for /firmware/
to test if it gets hit (it does). The /
route does not get a hit.
The behavior is the same whether I run the application via flask
or gunicorn
, that doesn't seem to matter.
What step have I missed / what am I doing wrong here? Why is the Flask application still getting requests for /firmware/
even though I've set up ProxyFix
and the HTTP headers?
Solution
In nginx add a trailing slash to your proxy proxy_pass http://localhost:6001/;
From the nginx documentation about proxy_pass
If the proxy_pass directive is specified with a URI, then when a request is passed to the server, the part of a normalized request URI matching the location is replaced by a URI specified in the directive:
location /name/ { proxy_pass http://127.0.0.1/remote/; }
If proxy_pass is specified without a URI, the request URI is passed to the server in the same form as sent by a client when the original request is processed, or the full normalized request URI is passed when processing the changed URI:
location /some/path/ { proxy_pass http://127.0.0.1; }
So in your case without the trailing slash, nginx was passing the request to flask (gunicorn) as http://localhost:6001/firmware
instead of http://localhost:6001/
Answered By - 0x00
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.