我有一个有缺陷的客户端,它Content-Type
在向特定 URL 发送 POST 时会发送错误的标头。有问题的 API 已经位于 nginx 1.15 反向代理后面,因此,作为一种解决方法,直到这些客户端可以修补为止,我只想重写Content-Type
这些请求的标头。我天真地尝试像这样设置它:
location /api/file {
if ($request_method = POST ) {
proxy_set_header Content-Type "application/octet-stream";
}
proxy_pass http://<api server>/api/file;
}
但是我收到此错误:
"proxy_set_header" directive is not allowed here
同一/api/file
端点还支持 GET 和 HEAD 方法,我更愿意保留它们。如何配置它以仅应用于proxy_set_header
POST 请求?
更新
现在我刚刚if
完全删除了块并全面应用了标头。发送Content-Type
GET 或 HEAD 毫无意义,但我的 API 服务器会在这些情况下忽略它,而且这已经是一种黑客行为了。
答案1
我会使用map
指令。
map $request_method $content_type_header {
default $http_content_type;
"POST" "application/octet_stream";
}
server {
...
location /api/file {
proxy_pass http://server/api/file;
proxy_set_header Content-Type $content_type_header;
}
}
答案2
你的做法违背了官方的建议。如果是邪恶的:
指令 if 在位置上下文中使用时会出现问题,在某些情况下,它不会按照您的预期执行,而是执行完全不同的操作。在某些情况下,它甚至会出现段错误。如果可能的话,最好避免这种情况。
看起来唯一正确的解决方法是完全禁用 if 中的非重写指令。不过这会破坏许多配置,所以还没完成。
如果你理解它的工作原理并做了适当的测试,那么你可以使用它。博客文章nginx “location if” 的工作原理在进一步研究这个逻辑时可能会变得方便:
简而言之,Nginx 的“if”块有效地创建了一个(嵌套的)位置块,并且一旦“if”条件匹配,则只有内部位置块(即“if”块)的内容处理程序才会被执行。
该错误"proxy_set_header" directive is not allowed here
可能是由嵌套的位置块中不再包含proxy_pass
指令引起的。
你可以想象你的外面的一切if
都在里面else
。我首先尝试像这样将其添加回来:
location /api/file {
if ($request_method = POST ) {
proxy_pass http://<api server>/api/file;
proxy_set_header Content-Type "application/octet-stream";
}
proxy_pass http://<api server>/api/file;
}
但您需要完成关键的部分:测试。