使用Nginx转发API请求遇阻,求排查与解决方案
我正在尝试用Nginx将API请求转发到外部API服务商,但试了很多方法还是有关键问题没解决。
我的需求是:当访问https://mywebsite/api/somedata时,实际调用远程API服务商的https://api-somewebsite.com/somedata。
初始基础配置
一开始用的配置是:
location /api/ { proxy_pass https://api-somewebsite.com/; }
添加日志排查问题
为了搞清楚请求细节,我添加了日志格式:
log_format upstreamlog '[$time_local] $remote_addr - $remote_user - $server_name $host to: $upstream_addr: $request $status upstream_response_time $upstream_response_time msec $msec request_time $request_time';
然后把这个日志格式应用到转发配置里:
location /api/ { proxy_pass https://api-somewebsite.com/; access_log /var/log/nginx/upstream.log upstreamlog; }
从日志里能看到,/api/路径并未被正确移除:
[21/Sep/2022:11:23:17 -0400] 88.163.105.196 - - - mywebsite.com mywebsite.com to: xxx.xx.xx.xx:xxx, xxx.xx.xx.xx:xxx: GET /api/somedata HTTP/1.1 502 upstream_response_time 0.005, 0.008 msec 1663773797.354 request_time 0.012
这说明实际请求的是https://api-somewebsite.com/api/somedata,而这个路径不存在,所以返回502错误。
尝试手动添加Rewrite规则
我了解到proxy_pass末尾加斜杠应该会自动移除/api/路径,但没生效,于是自己加了rewrite规则:
location /api/ { proxy_pass https://api-somewebsite.com/; access_log /var/log/nginx/upstream.log upstreamlog; rewrite ^/api/(.*) /$1 break; }
但问题还是没解决。
尝试添加proxy_redirect指令
之后我试了网上找的配置,加了proxy_redirect指令,但完全没理解它的作用:
location /api/ { proxy_pass https://api-somewebsite.com/; access_log /var/log/nginx/upstream.log upstreamlog; rewrite ^/api/(.*) /$1 break; proxy_redirect https://api-somewebsite.com/ /api/; }
我感觉自己缺一些基础配置知识,希望能得到相关建议。
编辑1:尝试Upstream配置
根据Stephen Dunne的回答,我给服务器加了upstream配置,修改后的完整代码如下:
upstream magiceden { server api-mainnet.magiceden.dev:443 max_fails=0; zone magiceden-api 64k; keepalive 60; } server { server_name genoverse.me www.genoverse.me; location / { root /home/hcomere/genoverse.me; index index.html; } location /magiceden_api/ { proxy_pass https://magiceden/; access_log /var/log/nginx/access_magiceden.log upstreamlog; } listen [::]:443 ssl; # managed by Certbot listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/genoverse.me/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/genoverse.me/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot }
访问https://www.genoverse.me/magiceden_api/时还是返回502错误(Bad Gateway),而预期应该收到API服务商https://api-mainnet.magiceden.dev/返回的400错误(Not found)。
编辑2:发现浏览器重定向缓存问题
哦,我发现浏览器有重定向缓存,这就解释了为什么有时候修改配置后没生效。每次改完配置清除重定向缓存,问题就变得更清晰好处理了!
内容的提问来源于stack exchange,提问作者Grizzant Grizzant

