我已经将nginx设置为反向代理,背景为gunicorn。这个网络服务器设置提供了我的Django应用程序,该应用程序具有一个postgresql后端。整个设置托管在两台Ubuntu计算机上(一个是应用程序计算机,另一个是DB计算机)。
我仅通过gunicorn测试了此设置,没有使用nginx。工作完美。接下来将其投入生产,我在gunicorn前面添加了nginx反向代理。我立即遇到令人沮丧的错误:inet类型的无效输入语法:“”(当用户尝试登录我的Django应用时出现)
登录到我的应用程序的用户的IP地址保存在会话表中;Django自行完成。现在,众所周知的事实是Postgresql要求所有客户端IP都属于INET类(某些其他DB也允许字符串IP,但不允许postgres)。INET类型不允许“”(即空)值,而是为inet类型“”抛出错误的无效输入语法。
换句话说,我的nginx反向代理未将其值发送REMOTE_ADDR
到Django应用。单独使用gunicorn可以正确设置该值(因此一切正常)。我如何让nginx 在Django的request.META中将$remote_addr
值传递REMOTE_ADDR
给?
我已经尝试proto_set_header REMOTE_ADDR $remote_addr;
在location
/ etc / nginx / sites-avaialble / myproject文件中的块中添加该文件。它不起作用- HTTP_REMOTE_ADDR
稍后我可以在request.META中看到一个值,但REMOTE_ADDR
仍为''。
那么,如何在Django的request.META中设置REMOTE_ADDR(即客户端的IP地址)字段?也许我可以通过gunicorn明确地传递它?有人提到我应该在数据库端处理它-我不确定该怎么做?我应该编辑pg_hba.conf还是postgresql.conf之类的东西吗?我已经查看了这些文件,没有选项可以记录“允许IP的空值”。而且,我宁愿将$ remote_addr中的任何值传递给Django,而不是让所有已登录用户的IP为空。
而且不要忘了,如果我仅使用gunicorn,那么在Django的请求中,REMOTE_ADDR就会正确设置。所以我的猜测是问题出在我如何通过nginx传递它。
请帮忙!如果需要,可以随时询问更多信息。
/ etc / nginx / sites-available / myproject:
server { listen 80; server_name example.cloudapp.net; charset utf-8; underscores_in_headers on; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /home/mhb11/folder/myproject; } location / { proxy_pass_request_headers on; include proxy_params; proxy_pass http://unix:/home/mhb11/folder/myproject/myproject.sock; } error_page 500 502 503 504 /500.html; location = /500.html { root /home/mhb11/folder/myproject/templates/; } }
/ etc / nginx / proxy_params:
proxy_set_header Host $host; proxy_set_header User-Agent $http_user_agent; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE_ADDR $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;
小智.. 6
这是一个已知的问题。查看有关运行域套接字服务器时REMOTE_ADDR无效的讨论:https : //github.com/python-web-sig/wsgi-ng/issues/11
确保所有依赖关系保持不变的一件事是编写中间件,该中间件可以在Django项目级别解决您的问题。
例如,如下所示:
class XForwardedForMiddleware(): def process_request(self, request): if request.META.has_key("HTTP_X_FORWARDED_FOR"): request.META["HTTP_X_PROXY_REMOTE_ADDR"] = request.META["REMOTE_ADDR"] parts = request.META["HTTP_X_FORWARDED_FOR"].split(",", 1) request.META["REMOTE_ADDR"] = parts[0]
(来源)
尝试一下,肯定可以解决您的问题。
这是一个已知的问题。查看有关运行域套接字服务器时REMOTE_ADDR无效的讨论:https : //github.com/python-web-sig/wsgi-ng/issues/11
确保所有依赖关系保持不变的一件事是编写中间件,该中间件可以在Django项目级别解决您的问题。
例如,如下所示:
class XForwardedForMiddleware(): def process_request(self, request): if request.META.has_key("HTTP_X_FORWARDED_FOR"): request.META["HTTP_X_PROXY_REMOTE_ADDR"] = request.META["REMOTE_ADDR"] parts = request.META["HTTP_X_FORWARDED_FOR"].split(",", 1) request.META["REMOTE_ADDR"] = parts[0]
(来源)
尝试一下,肯定可以解决您的问题。