New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Possible to make gevent respect SCRIPT_NAME env var? #1667
Comments
Can you be specific about what change you're proposing, and how it relates to the WSGI specification? Note that gevent is in no way flask specific. |
Yes, I know this 😏 I believe it relates to attaching SCRIPT_NAME from It looks like gevent currently sets SCRIPT_NAME to an empty string indiscriminately. In (Pdb) p request.environ["SCRIPT_NAME"] # gunicorn
'/foo'
(Pdb) p request.environ["SCRIPT_NAME"] # gevent
'' Again, I understand the concern in this repo is not with Flask, but stepping into (Pdb) p endpoint
'static'
(Pdb) p values
{'filename': 'favicon.ico'}
(Pdb) p url_adapter.build(endpoint, values, method=method, force_external=external)
'/foo/static/favicon.ico' To bring it back to gevent, the recognition and management of SCRIPT_NAME seems to be standard across different wsgi app servers, so I'm wondering if there is a way to achieve this effect with gevent, or why the behavior seems to differ. |
The WSGI PEP mostly imports many environment variables from the CGI spec. The CGI spec says of
An empty value for The WSGI PEP tightens this slightly:
As far as gevent knows, there is only one application, and it is the root. There is no concept of any hierarchy of application objects or any relation to URL space or filesystem layout. So an empty
I disagree. The "implementation defined manner" seems to be quite different across servers. I agree that gunicorn will read a In contrast, waitress requires the command-line argument
The standard library reference implementation also just hardcodes an empty string, presumably for similar reasons to gevent. (It does read the process environment and add it to the WSGI environment, but the hardcoded variables replace whatever was in the process environment.) Given those examples, I don't see a clear consensus. It does seem like they all do something a bit differently. But, in all cases it should be pretty simple to make it do what your application expects. The most portable way would be with a tiny bit of WSGI middleware: def make_middleware(app):
def middleware(environ, start_response):
environ['SCRIPT_NAME'] = os.environ.get('SCRIPT_NAME', '')
return app(environ, start_response)
app = make_middleware(app) If you wish to rely directly on gevent, then one could also subclass class MyHandler(WSGIHandler):
def get_environ(self):
environ = super().get_environ()
environ['SCRIPT_NAME'] = os.environ.get('SCRIPT_NAME', '')
server = WSGIServer(":8080", app)
server.handler_class = MyHandler
server.serve_forever() |
Fair enough - admittedly, using Gunicorn as a single example in my original question means using "across servers" without additional evidence was probably an overextended conclusion.
From my layman's perspective, this sounds correct but overly theoretical. A common structure is Nginx as reverse proxy -> Gevent -> Flask/Django. It seems like needing to subclass |
Again, I disagree. That’s not a common setup in my experience. Production use tends towards something reasonable, like Pyramid+gunicorn, which doesn’t suffer from this issue. Nonetheless, it seems there is nothing reasonable for gevent to do here. This is a portability issue with other trivial solutions. Thank you for your post! |
Background:
/foo
to a Flask application root sitting behind gevent as wsgi app serverSCRIPT_NAME
fromrequest.environ
in generation ofurl_for()
resultsurl_for()
will be lacking the correct prefixhref="{{ url_for('static', filename='favicon.ico') }}"
breaks, since it generates an absolute path without the prefix fromSCRIPT_PATH
.Case 1 (unexpected/non-working results, gevent):
hello.py:
Start:
$ SCRIPT_NAME='/foo' python hello.py
Result:
to
is/static/favicon.ico
.Case 2 (expected results, gunicorn):
hello.py:
Start:
The
url_for()
call produces/foo/static/favicon.ico
correctly.The text was updated successfully, but these errors were encountered: