我无法决定这个问题的最佳名称。
-
基本上我想实现的是为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
正是这种指令,所以上面的配置不起作用。