【问题标题】:Unable to get nginx internal redirect to work无法让 nginx 内部重定向工作
【发布时间】:2016-02-22 19:41:27
【问题描述】:

我正在使用 ubuntu 14.04 并运行 nginx 1.4.6 作为反向代理服务器来与我在 uwsgi 上运行的 django 后端通信。我无法让内部重定向工作,也就是说,请求根本没有到达 django。这是我的 nginx 配置 /etc/nginx/site-enabled/default 文件。请让我知道我的配置有什么问题。

server {
        listen 8080;
        listen 8443 default_server ssl;
        server_name localhost;
        client_max_body_size    50M;
        access_log      /var/log/nginx/nf.access.log;
        error_log       /var/log/nginx/nf.error_log debug;
        ssl_certificate      /etc/ssl/nf/nf.crt;
        ssl_certificate_key  /etc/ssl/nf/nf.key;
        location / {
                proxy_pass http://localhost:8000;
        }
        location /static/ {
                root /home/northfacing;
        }
        location /media/ {
                internal;
                root /home/northfacing;
        }
}

添加我的 uwsgi 配置。

[uwsgi]
chdir=/home/northfacing/reia
module=reia.wsgi:application
master=True
pidfile=/home/northfacing/reia/reia-uwsgi.pid
vacuum=True
max-requests=5000
daemonize=/home/northfacing/reia/log/reia-uwsgi.log
http = 127.0.0.1:8000

添加我的 uwsgi 启动脚本

#!/bin/bash
USER="northfacing"
PIDFILE="/home/northfacing/reia/reia-uwsgi.pid"

function start(){
    su - ${USER} /bin/sh -c "source /home/northfacing/nfenv/bin/activate && exec uwsgi --pidfile=${PIDFILE} --master --ini /etc/init.d/reia-uwsgi.ini"
}

function stop(){
    kill -9 `cat ${PIDFILE}`
}

$1

/home/northfacing/nfenv 是我的python环境目录。

【问题讨论】:

  • 你要从哪个网址重定向到哪个网址?
  • 另外,如果您使用的是 uWSGI,请考虑使用本机 uwsgi 协议 (uwsgi_pass) 而不是 proxy_pass
  • 你做了什么,什么不工作?
  • 你在 8000 端口上运行 uwsgi 吗?显示您的配置以及如何启动它。你使用什么 URL 来访问 nginx?
  • 什么?这根本不是您的配置所说的。 /media(如 /static)直接路由到 /home/northfacing 的文件系统,并且不通过 Django。

标签: django nginx x-accel-redirect


【解决方案1】:

如果您希望 django 处理访问媒体文件的权限,首先要做的是将所有请求传递给 django。我假设/home/northfacing 是您的项目根目录(默认情况下将放置manage.py 的目录),您的静态文件被收集到项目的public/static 子目录中,媒体文件存储在public/media 中。

基于该假设,以下是该行为的基本配置:

server {

    listen 8080;
    server_name localhost;

    client_max_body_size 50M;

    access_log      /var/log/nginx/nf.access.log;
    error_log       /var/log/nginx/nf.error_log debug;
    ssl_certificate      /etc/ssl/nf/nf.crt;
    ssl_certificate_key  /etc/ssl/nf/nf.key;

    root /home/northfacing/public/;

    location @default {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        include /etc/nginx/proxy_params;

        proxy_pass softwaremind_server;
        break;
    }

    location /static/ {
        try_files $uri @default; # just some simple default action, so you can show django's 404 page instead of nginx default
    }

    location /media/ {
        internal;
        error_page 401 403 404 = @default;
    }

    location / {
        try_files /maintenance.html @default; # you can disable whole page with simple message simply by creating maintenance.html with that message
    }
}

简单解释:对/media/中的url的所有请求都被视为内部的,所以直接输入nginx会服务404、401或403错误。但是在那个位置,我们的代理服务器(在这种情况下是 django)被设置为处理程序,因此它将获取请求并能够检查用户是否具有访问权限。

如果没有访问权限,django 会抛出它自己的错误。如果授予访问权限,django 应该返回一个空响应,并将 X-Accel-Redirect 设置为文件路径。其简单视图如下所示:

class MediaView(View):

    def get(self, request):

        if not request.user.is_authenticated():
            raise Http404

        response = HttpResponse()
        response.status_code = 200
        response['X-Accel-Redirect'] = request.path

        # all this headers are cleared-out, so nginx can serve it's own, based on served file
        del response['Content-Type']
        del response['Content-Disposition']
        del response['Accept-Ranges']
        del response['Set-Cookie']
        del response['Cache-Control']
        del response['Expires']
        return response

urls.py:

    url(r'^media/', MediaView.as_view(), name="media")

【讨论】:

  • 感谢您的详细配置。我仍然面临的一个问题是,任何以 /media/ 开头的 uri 都不会转发到上游。只有当我在 nginx 配置中有 /media/* 时才会这样做。但是,这会产生一组内部重定向循环,最终 nginx 会抛出 500 错误。仍在为此苦苦挣扎。
  • 检查我的确切配置,它对我来说就像 nginx 1.9.3 的魅力一样。您还可以将proxy_pass 更改为uwsgi_pass 并重新配置您的uWSGI 以使用uwsgi 协议。还要检查 uWSGI 和 django 日志(如果有),也许这个 500 错误来自它们,而不是来自 nginx。
  • 希望我能给超过 1 票。经过几个小时的尝试解决这个问题,这个答案帮助了我,并且是其他几个选项中最好的配置,IMO。谢谢!
【解决方案2】:

这是我对内部重定向如何工作的误解。根据下面的文档 http://nginx.org/en/docs/http/ngx_http_core_module.html#internal nginx 配置中的内部设置意味着来自外部源的具有该 uri 的任何请求都将使用 404 服务。它只能来自内部。在我的情况下, /media 也是从客户端使用的。所以,这被 nginx 忽略了。以下配置有效。

在 nginx 中,我有以下配置。请注意,/media 已被删除。

location /protected/ {
    internal;
    alias /home/northfacing/media/;
}

location / {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://127.0.0.1:8000;
}

在 python 视图中,

def protect_uploads(request):
    if settings.DEBUG == False:
        response = HttpResponse()
        response.status_code = 200
        protected_uri = request.path_info.replace("/media", "/protected")
        response['X-Accel-Redirect'] = protected_uri
        del response['Content-Type']
        del response['Content-Disposition']
        del response['Accept-Ranges']
        del response['Set-Cookie']
        del response['Cache-Control']
        del response['Expires']
        logger.debug("protected uri served " + protected_uri)
        return response

感谢您的所有建议。这导致了不同的实验并最终解决了问题。

【讨论】:

    猜你喜欢
    • 2018-05-18
    • 2018-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-05
    • 2021-08-11
    • 2017-05-15
    • 1970-01-01
    相关资源
    最近更新 更多