gunicorn via mod_proxy is redirecting outside of the project's scope, despite ProxyPassReverse

a 夏天 提交于 2019-12-09 17:07:43

问题


I have a WSGI-app (a Django project) running under gunicorn on 127.0.0.1:18731 and I use Apache with mod_proxy to redirect requests from http://example.com/my-project/* to http://127.0.0.1:18731/*. Static files are stored outside of /my-project/. If the Django app does not need to redirect anything, this works just fine, but if it tries to redirect a request (e.g. to add a trailing slash to http://example.com/my-project/foo), it ends up removing /my-project/ from the URL, leaving me with the invalid URL http://example.com/foo/.

My mod_proxy configuration is as follows:

<Proxy *>
    Order deny,allow
    Allow from all
</Proxy>
ProxyRequests On
ProxyPass /my-project/ http://127.0.0.1:18731/ retry=0
ProxyPassReverse /my-project/ http://127.0.0.1:18731/ retry=0
ProxyPreserveHost On
ProxyErrorOverride Off

I do not want to force Django to prefix /my-project/ to all of its URLs, in the interest of portability. Apache should apparently be handling the prefix on its own with the ProxyPassReverse line. What am I doing wrong?


回答1:


I had this problem to.

ProxyPreserveHost On

<Location "/my-project/">
    ProxyPass http://127.0.0.1:18173/my-project/
    ProxyPassReverse http://127.0.0.1:18173/my-project/
    RequestHeader set SCRIPT_NAME /my-project
    RequestHeader set X-FORWARDED-PROTOCOL ssl
    RequestHeader set X-FORWARDED-SSL on
</Location>

To enable the WSGI app to construct an absolute url we need:

  • ProxyPreserveHost On, so the Host: header gets passed and the app knows the Hostname the client sees us at.
  • Add a SCRIPT_NAME header so the app knows where its root is.
  • Set X-FORWARDED- headers as needed. I'm using ssl too, so I have to tell the app it should use the https scheme.

I use <Location> directives, because I do a lot more stuff on this vhost. But you can easily rewrite this by passing path arguments to the ProxyPass and ProxyPassReverse directives.

NB: ProxyRequests should be Off, unless you want a forward proxy too. If you're reading this you probably only want a reversed proxy.

Django specific note: settings.LOGIN_URL is used as is, so you'll need to prepend the SCRIPT_NAME to it yourself.




回答2:


Did you try this? I added my-project to the url you are proxying too.

<Proxy *>
    Order deny,allow
    Allow from all
</Proxy>
ProxyRequests On
ProxyPass /my-project/ http://127.0.0.1:18731/my-project/ retry=0
ProxyPassReverse /my-project/ http://127.0.0.1:18731/my-project/ retry=0
ProxyPreserveHost On
ProxyErrorOverride Off

I normally use nginx for this sort of thing, so I'm not sure if that will work or not.

Update: the above didn't work so trying something else.

Try something like this and see if that helps. It is setup a little different. It proxies everything except media which is served via an alias. This remove the need to have /my-project/ at all.

<VirtualHost *:80>
ServerName example.com
UseCanonicalName On
ServerAdmin webmaster@localhost

LogLevel warn
CustomLog /var/log/apache2/example.com/access.log combined
ErrorLog /var/log/apache2/example.com/error.log
ServerSignature On

Alias /media/ /home/example/example.com/pysrc/project/media/

ProxyPass /media/ !
ProxyPass / http://127.0.0.1:18731/
ProxyPassReverse / http://127.0.0.1:18731/
ProxyPreserveHost On
ProxyErrorOverride Off
</VirtualHost>



回答3:


I have solved the original problem by setting the ProxyPassReverse config to the actual domain name:

ProxyPass /my-project/ http://127.0.0.1:18731/
ProxyPassReverse /my-project/ http://mydomain.com/

Hint: Apache ProxyPassReverse values



来源:https://stackoverflow.com/questions/6418016/gunicorn-via-mod-proxy-is-redirecting-outside-of-the-projects-scope-despite-pr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!