我正在尝试在一些内部 Web 服务前面放置一个反向代理。
Nginx 已设置并正常工作以处理请求。如果我location /
在 conf 文件中只提供一个,它会成功加载该 proxy_pass 目标,即:
location / {
proxy_pass https://internal.ip:port/;
}
浏览至https://public_proxy_address/完美加载内部资源。
但是,由于我有多个内部应用程序,我想通过 nginx 代理所有应用程序。因此,在测试中,我将配置更改为如下:
location /app1 {
proxy_pass https://internal.ip:port/;
}
完成这些后,我得到了主/默认内部应用程序索引页,但查看源代码显示没有链接样式表、js 或其他资源正在被重写。因此,页面的所有内容都无法加载。在 Apache 中,我可能会编写一个proxyhtmlurlmap ^/resource/ /app1/resource R
。但我找不到在 nginx 中实现此目的的任何方法。
我也尝试过这个,但没有成功:
location /app1 {
rewrite /resource(.*?) /app1/resource$1 break;
proxy_pass https://internal.ip:port/;
}
如何让 nginx 正确地将目标位置(app1)添加到请求的资源 URL 前面,以便它们加载?
答案1
由于我没有足够的信用,我无法对条目发表评论,因此,我的回应作为单独的条目出现。
我不知道原帖作者为什么不同意,但我认为 Martin Fjordval 正确地指出了问题并提出了正确的建议。不过我建议对他的代码片段进行如下修改;
location /app1/ {
proxy_set_header Host $http_host/app1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
add_header Pragma "no-cache";
add_header Cache-Control "no-cache";
proxy_pass http://internal.ip:port/;
sub_filter 'action="/' 'action="/app1/';
sub_filter 'href="/' 'href="/app1/';
sub_filter 'src="/' 'src="/app1/';
sub_filter_once off;
}
因此,如果您确定所有以“/”开头的相对 URL 都需要重定向,则上述代码会将“/app1/”附加到所有 URL 上,并在引用时让“location /app1/”块捕获它们。然后,您可以查看页面源代码并确认重写正在进行。
您可能还需要整个或至少部分“proxy_set_header”shabang,尤其是“proxy_set_header Host $http_host/app1”位。
答案2
我最终选择了基于子域名的代理。基本原理如下:
server {
listen 443 ssl;
ssl on;
ssl_cert <cert>;
ssl_key <key>;
server_name appname1.public.com;
location / {
proxy_pass https://internalapp1.ip:port
}
}
server {
listen 443 ssl;
ssl on;
ssl_cert <cert>;
ssl_key <key>;
server_name appname2.public.com;
location / {
proxy_pass https://internalapp2.ip:port
}
}
这样就无需进行任何直接的 URL 或资源重写。
答案3
如果我正确理解了您的问题,那么问题似乎是您的应用程序认为它托管在根 uri 上,/
而实际上它托管在/app1
,只是没有被告知这一点。Nginx 通常不会修改后端的响应,这是您所期望的,但是,这是可能的。
首先,您需要检查应用中是否有可以定义根 uri 的配置选项。如果有,那么设置是迄今为止最简单的解决方案。
如果你找不到任何东西,你可以使用替代模块替换 HTML 中的 URL。请注意,要使此功能正常工作,您需要在后端禁用 GZIP 编码,以便 nginx 可以看到未压缩的 HTML。
子过滤器的示例
location /app1 {
sub_filter '<a href="/resource/' '<a href="/app1/resource/';
sub_filter_once off;
proxy_pass https://internal.ip:port/;
}
答案4
我遇到了同样的问题;索引页正在加载,但所有资源都收到 404。
我注意到在我所在的位置:try_files $uri $uri/ =404;
这会为所有资源返回 404。只需将其删除即可。
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
# try_files $uri $uri/ =404; <---- Comment out this line.
# Uncomment to enable naxsi on this location
# include /etc/nginx/naxsi.rules
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}