I have a Pyramid application which uses request.environ['REMOTE_ADDR'] in some places.
The application is served by Python Paste on port 6543 and a nginx server listening on port 80 is forwarding requests to the Paste server.
The nginx configuration is inspired by the Pyramid cookbook:
server {
listen 80; ## listen for ipv4
listen [::]:80 default ipv6only=on; ## listen for ipv6
server_name localhost;
access_log /var/log/nginx/localhost.access.log;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:6543;
}
In the Pyramid application the variable request.environ[‘REMOTE_ADDR’] is now always equal to 127.0.0.1.
I see a few strategies to solve this problem but I don’t know if there is a recommended way to do that.
Here is what I’m considering:
-
add a NewRequest subscriber which replaces request.environ[‘REMOTE_ADDR’] if necessary:
if 'HTTP_X_REAL_IP' in event.request.environ:
event.request.environ['REMOTE_ADDR'] = event.request.environ['HTTP_X_REAL_IP'] -
use a wsgi middleware to modify request.environ before hitting the Pyramid layer.
-
something else
Which strategy do you use for deploying Pyramid applications ?
What will happen if I have two nginx proxies ? (the first serving the LAN and a second one one a machine directly connected to the internet).
If you use the
paste.deploy.config.PrefixMiddlewarein your WSGI pipeline viause = egg:PasteDeploy#prefix, it will automatically translateX-Forwarded-ForintoREMOTE_ADDR. It is also great for other properties of your reverse proxy, for example it will translateX-Forwarded-Protointowsgi.url_schemeto ensure that if the user visits with https then generated URLs are also https.http://pythonpaste.org/deploy/class-paste.deploy.config.PrefixMiddleware.html