共享nginx中的位置配置



我无法决定这个问题的最佳名称。

  • 基本上我想实现的是为web服务器上的特定位置设置自定义允许的正文大小。

  • 另一方面,我已经能够用重复的代码实现必要的结果,所以我真的在寻找一种方法,如何使代码可重用,并更好地理解观察到的行为。

服务器将所有API请求反向代理到后端服务。

在全局nginx配置/etc/nginx/nginx.conf中,我设置了最大允许体大小的规则,如client_max_body_size 50k;

然后,在单个服务器配置/etc/nginx/conf.d/example.com中,我有以下配置(简化):

server {
    listen 80;
    listen [::]:80;
    
    server_name api.example.com www.api.example.com
    
    location ~* /file/upload {
        client_max_body_size 100M;
        # crashes without this line
        proxy_pass http://localhost:90;
        #proxy_pass http://localhost:90/file/upload; # also works
    }
        
    location / {
        # does not work
        #location ~* /file/upload {
        #   client_max_body_size 100M;
        #}
        
        proxy_pass http://localhost:90;
    }
}

我正在尝试覆盖文件上传端点的最大正文大小。看到位置/file/upload有1个proxy_pass,位置/有另一个proxy_pass,指向相同的内部服务。

问题1 。如果我从位置/file/upload中删除proxy_pass,则服务器返回错误。(在chrome调试器中没有状态代码)。为什么会发生这种情况?请求不应该进一步传播到位置/吗?

问题2 。为什么不可能在/位置内定义体大小覆盖的子位置,如上面示例中的注释部分?如果我像这样设置它,那么返回413错误代码,这提示忽略了client_max_body_size 规则。

问题3 。最后,是否有可能告诉nginx,在请求命中/file/upload位置后-应用/部分的所有规则?我想这个问题的一个解决方案是将公共配置移动到单独的文件中,然后在两个部分中导入它。我在想,如果有任何解决方案,不需要创建新的文件?

这是我主要谈论的可重用配置:

location / {
    #.s. kill cache. use in dev
    sendfile off;
    # kill cache
    add_header Last-Modified $date_gmt;
    add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
    if_modified_since off;
    expires off;
    etag off;
    
    # don't cache it
    proxy_no_cache 1;
    # even if cached, don't try to use it
    proxy_cache_bypass 1; 
    
    proxy_pass http://localhost:90;
    
    client_max_body_size 100M;
    
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Server $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_set_header Host $http_host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    proxy_pass_request_headers on;
}

这不是最终版本。如果我必须将这段代码复制到两个部分,这将不是一个非常友好的方法。所以,很高兴听到一些nginx生活技巧,关于如何以最友好的方式完成我试图完成的任务,并得到一些观察到的行为的解释。

答案1

如果我从位置/file/upload中删除proxy_pass,则服务器返回错误。(在chrome调试器中没有状态代码)。为什么会发生这种情况?

每个位置都有一个所谓的内容处理程序。如果你没有通过proxy_pass (fastcgi_pass, uwsgi_pass等)指令明确指定内容处理程序,nginx将尝试本地服务请求。

请求不应该进一步传播到位置/吗?

当然不是。你凭什么认为应该?

回答2

为什么不可能在/位置内定义体大小覆盖的子位置,如上面示例中的注释部分?如果我像这样设置它,那么返回413错误代码,这提示忽略了client_max_body_size规则。

我宁愿希望你会得到相同的错误在第一种情况下,因为你的嵌套位置没有通过proxy_pass指令显式指定的内容处理程序。但是下面的配置值得一试:

location / {
    # all the common configuration
    location /file/upload {
        client_max_body_size 100M;
        proxy_pass http://localhost:90;
    }
    proxy_pass http://localhost:90;
}

答案 3

最后,是否有可能告诉nginx,在请求命中/file/upload位置后-应用/部分的所有规则?

不能,除非你在两个位置通过include指令使用一个单独的文件。但是,您可以尝试将所有上游相关的设置指令移动到server上下文中:

server {
    ...
    # all the common configuration
    location / {
        proxy_pass http://localhost:90;
    }
    location /file/upload {
        client_max_body_size 100M;
        proxy_pass http://localhost:90;
    }
}

注意一些指令(例如add_header, proxy_set_header)是从上一个配置级别继承的,当且仅当当前级别没有定义这些指令时。

通常可以通过以下方式使用map块实现不同位置的动态设置:

map $uri $max_body_size {
    ~^/file/upload    100M;
    default           50k;
}
server {
    location / {
        ...
        client_max_body_size $max_body_size;
        ...
    }
}

不幸的是,并不是每个nginx指令都接受变量作为参数。通常当nginx文档没有明确说明某些指令可以接受变量时,这意味着它不能,而client_max_body_size正是这种指令,所以上面的配置不起作用。

最新更新