如何转发来自我的 Web 服务器的请求?

Ger*_*der 5 nginx reverse-proxy apache2

这是一个关于反向代理、它们如何工作以及如何配置的规范问题

如何处理来自不同端口上的服务或来自具有相同网络服务器的不同服务器的请求并通过 URL 区分它?

Ger*_*der 7

如果您想提供来自多个服务或来自同一域的多个服务器的服务内容,您可以将您的网络服务器配置为充当反向代理。服务(通常称为后端服务器应用程序服务器)不一定需要从客户端直接可达,通常只有实际为客户端提供服务的 Web 服务器才可直接可达。客户端和服务器之间以及服务器和后端之间也可以有不同的方案或协议(http、https、ajp、...)。

Client ---[https]---> Server ---[http]---> backend:8080
                       |
                       |---[direct]---> files from document root
                       `---[http]---> localhost:4000
Run Code Online (Sandbox Code Playgroud)

例子

反向代理可以配置为虚拟目录或子域。

Apache 的示例配置

您需要加载必要的 apache 模块才能将其用作反向代理。这些至少是:

对于更多协议,您将需要启用更多模块。

您可以使用基于 Debian/Ubuntu 的发行版启用模块,如下所示:

sudo a2enmod proxy proxy_http
Run Code Online (Sandbox Code Playgroud)

对于基于 RedHat/CentOS 的发行版,您需要在其中找到正确的配置文件/etc/httpd/并手动启用模块。

上述示例的配置可能如下所示:

<VirtualHost *:443>
  ServerName example.com
  DocumentRoot /var/www/html
  
  # SSL options left out for simplicity
  
  ProxyRequests         Off
  ProxyPreserveHost     On
  ProxyPass               /jenkins/ http://192.168.42.18:8080/
  ProxyPassReverse        /jenkins/ http://192.168.42.18:8080/
</VirtualHost>

<VirtualHost *:443>
  ServerName api.example.com
  DocumentRoot /var/www/html
  
  # SSL options left out for simplicity

  ProxyRequests         Off
  ProxyPreserveHost     On
  ProxyPass               / http://localhost:4000/
  ProxyPassReverse        / http://localhost:4000/
</VirtualHost>
Run Code Online (Sandbox Code Playgroud)

nginx 配置示例

server {
  listen 443;
  server_name example.com;
  root /var/www/html;
  
  # SSL options left out for simplicity

  location /jenkins/ {
    proxy_pass http://192.168.42.18:8080/;
  }
}

server {
  listen 443;
  server_name api.example.com;
  
  # SSL options left out for simplicity
  
  location / {
    proxy_pass http://localhost:4000/;
  }
}
Run Code Online (Sandbox Code Playgroud)

后端配置

One thing to keep in mind is that the backend server should be configured accordingly. If, for example, Jenkins is configured to serve requests with the URL http://192.168.42.18:8080/, it will use this base URL for paths to CSS, JS, and image files, resulting in a lot of 404 errors or timeouts and a non working server. It has to be configured with the proxy URL https://example.com/jenkins/ as a base URL to make it work.

Other backends require a similar configuration. This is the preferred method of resolving issues with URLs pointing to the backend server instead of the frontend server. If for some reason it is not possible to change the configuration of the backend server, you can configure the frontend server to rewrite the HTML before serving it to the client.

但是,这应该被视为最后的手段,因为它会给前端服务器增加不必要的负载。

阿帕奇

使用 Apache,您可以使用该模块mod_proxy_html。该模块提供指令ProxyHTMLURLMap,您可以使用它来重写响应。

ProxyPass               /jenkins/ http://192.168.42.18:8080/
ProxyPassReverse        /jenkins/ http://192.168.42.18:8080/
SetOutputFilter proxy-html # make sure the output is filtered by proxy-html
ProxyHTMLURLMap http://192.168.42.18:8080/ https://example.com/jenkins/
ProxyHTMLExtended On       # by default only HTML output is filtered
Run Code Online (Sandbox Code Playgroud)

这应该使用 publichostname URL 重写答案中所有出现的 localserver URL。

nginx

使用 nginx 可以通过ngx_http_sub_module实现类似的结果:

  location /jenkins/ {
    proxy_pass http://192.168.42.18:8080/;
    sub_filter '<a href="http://192.168.42.18:8080/'  '<a href="https://$host/jenkins/';
    sub_filter_once on;
  }
Run Code Online (Sandbox Code Playgroud)