使用 Django Rest Framework 的 POST 图像请求的 nginx 返回 500

nginx Returning 500 for POST Image Request with Django Rest Framework

前言

我已经为解决我一直遇到的类似问题做了很多研究,但仍然没有解决我遇到的这个主要问题。作为最后的手段,由于很多情况似乎都是特定于应用程序的,所以我决定在此处使用我的配置创建一个 post,希望有人能看到可能的解决方案。

框架

Django 2.1.7
nginx/1.14.2
djangorestframework==3.9.2

问题

在使用上述框架对我的服务器进行本地设置时,我可以 POST 通过我的客户端应用程序(特别是 react-native 应用程序,这可能不是重要信息)的图像就好了。 但是,当尝试使用相同的图像和 URL 路径向我的 远程 服务器发出相同的 POST 请求时,它 return 出现以下 500 错误(来自 Google Chrome 控制台调试器的快照)。

我强烈推断 nginx 是图像上传的罪魁祸首,因为我的远程服务器的 django 日志没有显示它甚至像我的本地服务器那样收到了 POST 请求。 一个正常的 POST 没有图片上传的请求,然而,在 远程和本地服务器上工作得很好。

我试过的

正如在其他 post 中发现的那样,我已将 nginx.confclient_max_body_size 增加到非常大的 2000M。我还设置了以下 Django 设置:

FILE_UPLOAD_PERMISSIONS = 0o777

FILE_UPLOAD_MAX_MEMORY_SIZE = 2621440000

DATA_UPLOAD_MAX_MEMORY_SIZE = 2621440000

None 这些建议的解决方案已奏效。

我的配置

nginx.conf

user                        www;
worker_processes            auto;

events { worker_connections 1024; }
daemon off;

http {
    server_tokens off;
    sendfile      on;
    include       mime.types;

    default_type  application/octet-stream;

    gzip              on;
    gzip_http_version 1.0;
    gzip_proxied      any;
    gzip_min_length   500;
    gzip_disable      "MSIE [1-6]\.";
    gzip_types        text/plain text/xml text/css
                    text/comma-separated-values
                    text/javascript
                    application/x-javascript
                    application/atom+xml;

    # List of application servers
    upstream app_server {
        server 127.0.0.1:9090;
    }

    # PRODUCTION (also default)
    server {
        # Using an alias, not the actual server name
        server_name my-remote-server.com;

        # Running port
        listen 8080 default_server;
        client_max_body_size 100M;
        keepalive_timeout    15;

        # Principle difference between production
        if ($http_x_forwarded_proto = "http") {
            return 301 https://$host$request_uri;
        }

        # Don't serve .py files
        location ~ (\.py$|\.pyc$) {
            return 403;
        }

        # Static assets served directly
        location /static/ {
            alias           /var/app/myserver/src/site/static/;
            access_log      off;
            log_not_found   off;
        }

        location /media/ {
            alias           /var/app/myserver/src/myserver/media/;
            access_log      off;
            log_not_found   off;
        }

        # Proxying the connections
        location / {
            proxy_pass              http://app_server;
            proxy_redirect          off;
            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-Host $server_name;
        }
    }
}

大问题

  1. 为什么 nginx return 会出现 500 错误?
  2. 有没有办法从 nginx 获取更详细的错误消息以了解为什么它是 return500 错误?
  3. 我的 config/settings 设置是否符合我期望上传图片的方式,或者是否可以通过改进或缺失部分来解决此问题?

如有任何想法或反馈,我们将不胜感激。谢谢。

经过 trial/error 的大量研究和尝试,我找到了适合我的情况的解决方案。

nginx.conf中的http对象中,设置如下属性:

// nginx.conf

...
http { 
    ...
    client_max_body_size 50M; // this can be whatever max size you want
    client_body_temp_path /tmp/client_body_temp;
    ...
}
...

根据 nginx 文档,client_body_temp_path defines a directory for storing temporary files holding client request bodies(参考:http://nginx.org/en/docs/http/ngx_http_core_module.html#client_body_temp_path)。一旦请求变大(即通过图像上传),nginx 服务器需要一个地方来缓冲它处理整个请求。显然我的服务器没有默认临时路径 client_body_temp 的权限,所以我手动创建了一个路径为 /tmp/client_body_temp 的文件夹,权限为 chmod 744,服务器终于响应了使用 HTTP 200。/tmp 具有在一定时间后自动清理自身的额外好处)。

注意:更改 nginx.conf 文件后,您需要 运行 nginx -s reload 使用新配置刷新服务器(事先使用 nginx -t 进行检查格式正确)。

绝对希望这对人们有帮助,就像对我来说是一个巨大的解脱!