Pyramid: how to set SCRIPT_NAME in request.environ

2019-09-07 17:50发布

问题:

I have a Pyramid app proxied behind nginx for which I'm trying to set SCRIPT_NAME in request.environ.

I've tried:

  • exporting it in the shell pserve is running in
  • exporting it in the shell nginx is running in
  • defining it in the Pyramid configuration file
  • manually setting it on gevent.wsgi.WSGIServer.environ before serve_forever()

Non-standard values I define in the last step are available, but SCRIPT_NAME is always empty, which seems to indicate it's being overwritten from somewhere else.

How can I set it?

回答1:

Have a look at repoze.vhm.

It usually solves all my virtual hosting problems. (subpath, virtual root etc...). Biggest advantage of repoze.vhm is, that your pyramid app can stay completely unaware of the external url und path. You do have to be careful though, that you use request.route_url and other methods when generating urls for your site/app (but that should be good practice anyway).

https://github.com/repoze/repoze.vhm



回答2:

SCRIPT_NAME is set by the WSGI server on a per-request basis. If your server doesn't have a hook to set it (waitress has a url_prefix=... setting) then you can easily just add a middleware at the stop of your middleware stack that sets it for you. Instead of writing your own custom middleware you can also use the paste prefix middleware which will allow you to append to the SCRIPT_NAME. It also supports overriding wsgi.url_scheme via translating the X-Forwarded-Proto header which will help with https.

The best way to use the middleware is by adding it to your ini file. There are some good examples here in the waitress documentation. I will replicate one below just to be more clear. [1]

[app:myapp]
use = egg:mypackage#myapp

[filter:paste_prefix]
use = egg:PasteDeploy#prefix

[pipeline:main]
pipeline =
    paste_prefix
    myapp

[server:main]
use = egg:waitress#main
listen = 127.0.0.1:8080

http://docs.pylonsproject.org/projects/waitress/en/latest/#using-behind-a-reverse-proxy