This is a variant of the ReverseProxied solution from pocoo. As it depends on __call__ being called inside a wsgi environment, it does not work when the app is being run standalone with run().
ScriptNameHandler
We solve this by instead overriding the make_environ() function of WSGIRequestHandler inside a new class, ScriptNameHandler, and passing it as an argument to Werkzeug’s run_simple(), like so:
from werkzeug.serving import WSGIRequestHandler class ScriptNameHandler(WSGIRequestHandler): def make_environ(self): environ = super().make_environ() script_name = environ.get('HTTP_X_SCRIPT_NAME', '') if script_name: environ['SCRIPT_NAME'] = script_name path_info = environ['PATH_INFO'] if path_info.startswith(script_name): environ['PATH_INFO'] = path_info[len(script_name):] scheme = environ.get('HTTP_X_SCHEME', '') if scheme: environ['wsgi.url_scheme'] = scheme return environ
Then change
app.run()
to
app.run(request_handler=ScriptNameHandler)
Passing the http header X-SCRIPT-NAME to the app creates the value HTTP_X_SCRIPT_NAME in the environ variable.
Apache example
<Location "/test_subdir"> ProxyPass "http://localhost:8081" X-SCRIPT-NAME "/test_subdir" </Location>