nginx 反向代理 - 如何为多个应用程序提供服务

2024-01-13

我正在尝试使用 nginx 构建一个反向代理,以使我的项目中的所有内容都可以从单个地址访问。 对于单个服务,以下配置可以正常工作

/etc/nginx/sites-enabled/reverse-proxy.conf

server {
        listen 80;
        listen [::]:80;
        location  / {

        resolver 127.0.0.1;
        allow "x.x.x.x";
        deny   all;
        proxy_pass http://consul:8500;
    }

}

所以当我调用服务器的ip时x.x.x.x在我的浏览器中,我看到 Consul UI 和 URL 显示x.x.x.x/ui/dc1。除此之外,我看到 UI 成功请求了资产文件。

我的问题;是否有可能在同一台服务器上托管两个不同的服务并仅在不同的位置引用它们?例如,如果我想包含 Vault UI,那么我会考虑这样做:

server {
        listen 80;
        listen [::]:80;
        location  /consul {

        resolver 127.0.0.1;
        allow "x.x.x.x";
        deny   all;
        proxy_pass http://consul:8500;
    }

        location  /vault {

        resolver 127.0.0.1;
        allow "x.x.x.x";
        deny   all;
        proxy_pass http://vault:8200;
    }

}

但是我不确定是否可以通过这种方式完成。我得到的最远的结果是打开 Consul UI,但未找到所有其他子请求(即加载资产)。


UPDATE

我认为我的问题是我错误地使用location and proxy_pass

观察第一个配置(正在运行)

server {
        listen 80;
        listen [::]:80;
        location  / {

        resolver 127.0.0.1;
        allow "x.x.x.x";
        deny   all;
        proxy_pass http://consul:8500;
    }

}

如果我看一下curl命令curl localhost -L -vvvv

*   Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.18.0 (Ubuntu)
< Date: Fri, 10 Jul 2020 16:24:38 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 39
< Connection: keep-alive
< Location: /ui/
< 
* Ignoring the response-body
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'http://localhost/ui/'
* Found bundle for host localhost: 0x557b754549e0 [serially]
* Can not multiplex, even if we wanted to!
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /ui/ HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.18.0 (Ubuntu)
< Date: Fri, 10 Jul 2020 16:24:38 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 7806
< Connection: keep-alive
< Accept-Ranges: bytes
< Last-Modified: Fri, 10 Jul 2020 07:37:44 GMT
< 
<!DOCTYPE html>
<html lang="en" class="ember-loading">
...

我已经可以看到 html 了。但是,如果我将conf文件更改为:

server {
        listen 80;
        listen [::]:80;
        location  /consul/ {

        resolver 127.0.0.1;
        allow "x.x.x.x";
        deny   all;
        proxy_pass http://consul:8500;
    }

}

然后尝试这样称呼它curl localhost/consul -L -vvvv,我得到以下信息:

*   Trying 127.0.0.1:80...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /consul HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.18.0 (Ubuntu)
< Date: Fri, 10 Jul 2020 16:32:35 GMT
< Content-Type: text/html
< Content-Length: 178
< Location: http://localhost/consul/
< Connection: keep-alive
< 
* Ignoring the response-body
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'http://localhost/consul/'
* Found bundle for host localhost: 0x55ba7959f9e0 [serially]
* Can not multiplex, even if we wanted to!
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET /consul/ HTTP/1.1
> Host: localhost
> User-Agent: curl/7.68.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 404 Not Found
< Server: nginx/1.18.0 (Ubuntu)
< Date: Fri, 10 Jul 2020 16:32:35 GMT
< Content-Length: 0
< Connection: keep-alive

我将不胜感激关于这个问题的任何想法


你是对的,你正在使用location and proxy_pass错误的方式。当您使用

location /vault {
    proxy_pass http://vault:8200;
}

构造时,您将按原样将 URI 传递到上游,而很可能您想删除/vault来自它的前缀。为此,您应该使用这个:

location /vault/ {
    proxy_pass http://vault:8200/;
}

您可以阅读有关第一个和第二个差异的更多信息here https://stackoverflow.com/questions/53649885/a-little-confused-about-trailing-slash-behavior-in-nginx。然而,这仍然会阻止资产正确加载。

这个问题——如何在某个 URI 前缀下代理某个 Web 应用程序——在 stackoverflow 上被反复询问。唯一正确的方法是让您的代理应用程序仅通过相对 URL 请求其资产(考虑assets/script.js代替/assets/script.js) 或使用正确的前缀 (/vault/assets/script.js)。一些编写良好的应用程序能够检测它们是否在这样的 URI 前缀下使用,并在生成资产链接时使用它,一些应用程序允许通过某些设置指定它,但有些应用程序根本不适合这种使用。如果不满足这些要求,Web 应用程序将无法工作的原因非常明显 - 任何不以以下形式开头的 URL/vault不会匹配你的location /vault/ { ... }块并通过 main 提供服务location改为阻止。因此,最好的方法是修复您的网络应用程序,但是如果您确实无法修复,可以使用多种解决方法。

  • 一些 Web 框架已经使用相对 URL 构建其 Web 应用程序,但使用<base href="/">在头部部分index.html。例如,React 或 Angular 使用这种方法。如果你的 webapp 根目录中有这样一行index.html,只需将其更改为<base href="/vault/">.

  • 使用基于HTTP的条件路由Referer标头值。这种方法对于加载资源的单页面应用程序非常有效,但是如果 Web 应用程序包含多个页面,则这种方法将不起作用,在第一次从一个页面跳转到另一个页面后,正确的上游检测的逻辑将会中断。这是一个例子:

    map $http_referer $prefix {
        ~https?://[^/]+/vault/     vault;
        # other webapps prefixes could be defined here
        # ...
        default                    base;
    }
    
    server {
    
        # listen port, server name and other global definitions here
        # ...
    
        location / {
            try_files "" @$prefix;
        }
        location /vault/ {
            # proxy request to the vault upstream, remove "/vault" part from the URI
            proxy_pass http://vault:8200/;
        }
        location @vault {
            # proxy request to the vault upstream, do not change the URI
            proxy_pass http://vault:8200;
        }
        location @base {
            # default "root" location
            proxy_pass http://consul:8500;
        }
    
    }
    

    更新@2022.02.19

    这是使用条件重写的另一种可能的方法:

    server {
    
        # listen port, server name and other global definitions here
        # ...
    
        if ($http_referer ~ https?://[^/]+/vault/)
            # rewrite request URI only if it isn't already started with '/vault' prefix
            rewrite ^((?!/vault).*) /vault$1;
        }
    
        # locations here
        # ...
    
    }
    
  • 使用重写响应正文内的链接sub_filter指令来自ngx_http_sub_module http://nginx.org/en/docs/http/ngx_http_sub_module.html。这是最丑的一个,但仍然可以用作最后一个可用的选项。这种方法对性能有明显的影响。重写模式应根据上游响应正文确定。通常这种类型的配置看起来像

    location /vault/ {
        proxy_pass http://vault:8200/;
        sub_filter_types text/css application/javascript;
        sub_filter_once off;
        sub_filter 'href="/' 'href="/vault/';
        sub_filter "href='/" "href='/vault/";
        sub_filter 'src="/'  'src="/vault/';
        sub_filter "src='/"  "src='/vault/";
        sub_filter 'url("/'  'url("/vault/';
        sub_filter "url('/"  "url('/vault/";
        sub_filter "url(/"   "url(/vault/";
    }
    

更新@2022.02.19

ServerFault 中的相关线程:如何使用 nginx 反向代理正确处理相对 URL https://serverfault.com/questions/932628/how-to-handle-relative-urls-correctly-with-a-nginx-reverse-proxy.

使用时可能需要注意的事项sub_filter在 JavaScript 代码上:Nginx 作为同一域上两个 Nodejs 应用程序的反向代理 https://stackoverflow.com/a/70012067/7121513.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

nginx 反向代理 - 如何为多个应用程序提供服务 的相关文章

  • 从 Nginx 到 Express.js 上的 socket.io 的反向代理上“无法获取”

    我已经关注了通过私有网络让 Node js 在两台 Ubuntu 14 04 服务器上通过 Nginx 工作 Node js 位于 myappserver 上 通过私有 IP myprivatewebserver 访问 并通过 mypubl
  • 验证来自两个不同 URL 的 Keycloak 令牌

    我有一个Docker compose具有后端和前端组件的基于系统 后端写的是Python Flask并在多个 docker 容器中运行 前端编写为TypeScript with Angular 前端通过Restful API与后端进行通信
  • 为什么在生产中得到空 CSS 文件?

    我在文件中放入了很多css文件active admin css scss Active Admin s got SASS import active admin mixins import active admin base import
  • ./manage.py 使用 https 运行服务器

    manage py 运行服务器 0 0 0 0 8000 我使用上面的行作为我从 github 借用的代码的一部分 https github com ribeiroit boh puppet https github com ribeiro
  • 通过 nginx 入口控制器进行基本身份验证

    我正在使用 nginx 入口控制器 https kubernetes github io ingress nginx deploy https kubernetes github io ingress nginx deploy 在 AWS
  • 如何将亚马逊颁发的免费证书配置到nginx.config

    我已经安装了nginx服务器在Amazon Linux 2环境 在创建弹性负载均衡器期间 我创建了 Amazon 的免费证书 现在 我想通过以下方式访问我的服务器https port 443 我该如何配置这个SSL证书在nginx conf
  • Kubernetes nginx 入口控制器返回 502,但仅适用于 AJAX/XmlHttpRequest 请求

    我有一个在 nginx 入口控制器后面运行 Kubernetes 的 Web 应用程序 它对于请求浏览工作正常 但来自浏览器的任何 AJAX XMLHTTPRequest 都会从 nginx 收到 502 错误 我捕获了常规请求和 AJAX
  • Nginx反向代理(proxy_pass)不传递子文件夹

    我想在子文件夹配置中运行应用程序 Mattermost 例如 https www example com mattermost https www example com mattermost location mattermost gzi
  • 上传大文件(几 GB)时,nginx 返回内部服务器错误

    我在 nginx 后面有一个 Artifactory 上传大于 4 GB 的文件失败 我相当确定这是 nginx 的错误 因为如果文件从本地主机上传 上传到本地主机 则不会出现问题 nginx 设置为client max body size
  • Node + Express + Nginx 未设置 Cookie

    我有一个使用 Express 的 Node 应用程序 我尝试为我的客户端设置 cookie 它在本地环境 http 上运行良好 但是一旦我投入生产 https 我就很好地收到了cookie 我可以在响应中看到它 但它没有设置 任何想法 Ng
  • nginx - 记录 SSL 握手失败

    我正在运行启用了 SSL 的 nginx 服务器 我的协议 密码设置相当安全 我已经在 ssllabs com 上检查过它们 但是 因为这是一个由我无法控制的 http 客户端调用的 Web 服务 所以我担心兼容性 重点是 有没有办法在我的
  • Nginx - 自定义 404 页面

    Nginx PHP 在 fastCGI 上 对我来说非常有用 当我输入不存在的 PHP 文件的路径时 我不会得到默认的 404 错误页面 任何无效的 html 文件都会出现该错误页面 而只会得到 未指定输入文件 如何自定义此 404 错误页
  • nginx 反向代理 websocket

    nginx 现在支持代理 websockets 但我无法找到任何有关如何在没有单独的情况下执行此操作的信息location应用于使用 websocket 的 URI 的块 我见过一些人推荐这种方法的一些变体 location proxy h
  • 反向代理受 NTLM 保护的网站

    如何将请求代理到受 NTLM 保护的网站 例如团队基金会 and 共享点 我不断得到401 身份验证错误 根据这篇 Microsoft TechNet 文章 https www microsoft com technet prodtechn
  • Django + uwsgi + ngnix + 调试关闭 = 服务器错误(500)

    我正在尝试设置一个由 Django uwsgi Nginx 组成的生产服务器 我正在关注的教程位于此处http www panta info blog 3 how to install and configure nginx uwsgi a
  • nginx 反向代理到 apache-wordpress 可以工作,但到外部 url 的 proxy_pass 失败

    我有一个针对 apache wordpress 的 nginx 反向代理设置 效果很好 但是 根据位置需要重定向到失败的外部 url 请检查以下配置 这是一个有效的设置吗 https platform com https platform
  • nginx 和 uwsgi 非常大的文件上传(>3Gb)

    也许有人知道该怎么做 我正在尝试上传大于 3Gb 的文件 没问题 如果我使用以下配置上传高达 2Gb 的文件 Nginx client max body size 5g client body in file only clean clie
  • 常规请求期间 Django AJAX 请求未通过

    我有一个带有登录网页的 Django 站点 当提交页面上的登录表单时 它会执行登录视图 该视图会在其中运行一个需要很长时间处理 30秒左右 的函数 因此 为了在登录期间向客户端显示进度 一旦提交表单 登录页面上的 JS 函数就会开始向服务器
  • NGINX 上的 SSL 终止

    我已经购买了 SSL 证书 并在验证模数时正确地将其捆绑在一起 即https kb wisc edu middleware 4064 https kb wisc edu middleware 4064 那么哈希值是相同的 我已将证书和密钥移
  • 如何修复 Nginx 自动 301 重定向到带有尾部斜杠的相同 URL?

    当我尝试将 Web 应用程序的子目录中的索引文件访问到相同的 URL 但附加了斜杠 时 Nginx 出现了不良行为 它正在重新路由请求 我有一个简单的 Web 应用程序 其中设置了一个根目录和其中的许多子目录 每个子目录中都有一个 inde

随机推荐