Apache2 代理背后的 Symfony 5.3 有意外行为(在 ProxyPass/ProxyPassReverse 的浏览器中不正确 url)

Symfony 5.3 behind Apache2 proxy has unexpected behavior (incorrect url in browser with ProxyPass/ProxyPassReverse)

我想 运行 Apache 反向代理后面的 Symfony 5.3 应用程序,但它没有按预期工作

我在 Apache 反向代理后面有很多 Web 项目 Apache 服务器没有任何问题,但是这个让我无法接受:-/

场景:

设置 浏览器 代理服务器 应用服务器
设置: http://host/app1/login ProxyPass /app1/ http://192.168.1.1/
ProxyPassReverse /app1/ http://192.168.1.1/
http://192.168.1.1/login

我希望设置做什么:

流量 浏览器 代理服务器 应用服务器
浏览器 > 代理 > 应用服务器 浏览器请求 url
(例如 post 凭据)
/app1/login
代理将请求映射到应用
/login
服务器在 /login 控制器
中执行操作(并重定向到 /success 见下图)
流量 应用服务器 代理服务器 浏览器
应用服务器 > 代理 > 浏览器 应用服务器发送
/success重定向
代理映射响应
/app1/success
收到重定向指向/app1/success

现实生活中发生的事情:

流量 浏览器 代理服务器 应用服务器
浏览器 > 代理 > 应用服务器 浏览器请求 url
(例如 post 凭据)
/app1/login
代理将请求映射到应用
/login
服务器在 /login 控制器
中执行操作(并重定向到 /success 见下图)
流量 应用服务器 代理服务器 浏览器
应用服务器 > 代理 > 浏览器 应用服务器发送
/success重定向
### 错误###
### 错误###
### 错误 ###
代理不知何故不重写
/app1/success 而是去 /success
接收重定向 指向 /success
并调用 http://host/success
并转到 404(或更糟糕的东西)

我想要什么

Browser: Hey i post credentials to /app1/login
Proxy: Uhh, one moment.. that has to be /login - otherwise Server does not know
Server: Yo, /login seems good, go to /success, oh and load /this/css.file
Proxy: Err, just a second.. that has to be /app1/success aaand /app1/this/css.file - otherwise Browser get's confused
Browser: Yay, ill make my way to /app1/success
Browser: Whoa, what a nice design in /app1/this/css.file

大家开心!

让事情变得更糟

我已经(字面上)阅读了数百篇关于 this/similar 问题的 Stack post。

我已经阅读了 Apache、ModProxy、Symfony 的“所有”文档,并花了几天时间 Google。

现在希望得到这个运行宁很低,脑袋疼

问题

附加信息

已安装服务器:

Server/App 配置:

ProxyRequests Off
ProxyVia Off
ProxyPreserveHost On
ProxyTimeout 1200
ProxyReceiveBufferSize 4096

<VirtualHost *:80>

ProxyPass /app1/ http://192.168.1.1/
ProxyPassReverse /app1/ http://192.168.1.1/

</VirtualHost>
<VirtualHost *:80>

        DocumentRoot /var/www/public

        <Directory /var/www/public>
                AllowOverride All
        </Directory>

</VirtualHost>
    # Determine the RewriteBase automatically and set it as environment variable.
    # If you are using Apache aliases to do mass virtual hosting or installed the
    # project in a subdirectory, the base path will be prepended to allow proper
    # resolution of the index.php file and to redirect to the correct URI. It will
    # work in environments without path prefix as well, providing a safe, one-size
    # fits all solution. But as you do not need it in this case, you can comment
    # the following 2 lines to eliminate the overhead.
    RewriteCond %{REQUEST_URI}::[=14=] ^(/.+)/(.*)::$
    RewriteRule .* - [E=BASE:%1]

    # Sets the HTTP_AUTHORIZATION header removed by Apache
    RewriteCond %{HTTP:Authorization} .+
    RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0]

    # Redirect to URI without front controller to prevent duplicate content
    # (with and without `/index.php`). Only do this redirect on the initial
    # rewrite by Apache and not on subsequent cycles. Otherwise we would get an
    # endless redirect loop (request -> rewrite to front controller ->
    # redirect -> request -> ...).
    # So in case you get a "too many redirects" error or you always get redirected
    # to the start page because your Apache does not expose the REDIRECT_STATUS
    # environment variable, you have 2 choices:
    # - disable this feature by commenting the following 2 lines or
    # - use Apache >= 2.3.9 and replace all L flags by END flags and remove the
    #   following RewriteCond (best solution)
    RewriteCond %{ENV:REDIRECT_STATUS} =""
    RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/ [R=301,L]

    # If the requested filename exists, simply serve it.
    # We only want to let Apache serve files and not directories.
    # Rewrite all other queries to the front controller.
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ %{ENV:BASE}/index.php [L]

我终于让它工作了。

代理配置从这里更改:

<VirtualHost *:80>

    ProxyPass /app1/ http://192.168.1.1/
    ProxyPassReverse /app1/ http://192.168.1.1/

</VirtualHost>

对此:

<VirtualHost *:80>

    ProxyPass /app1/ http://192.168.1.1/app1/
    ProxyPassReverse /app1/ http://192.168.1.1/app1/

</VirtualHost>

现在指向应用服务器上的/var/www/public/app1/目录,该目录不存在

所以..在应用程序服务器上我改变了这个:

<VirtualHost *:80>

    DocumentRoot /var/www/public

    <Directory /var/www/public>
            AllowOverride All
    </Directory>

</VirtualHost>

对此:

<VirtualHost *:80>

    DocumentRoot /var/www/public

    Alias /app1 /var/www/public

    <Directory /var/www/public>
            AllowOverride All
    </Directory>

</VirtualHost>

.. 和 DING .. 它正在工作。

由于使用了 webpack 配置,因此需要进行一些额外的应用故障排除。必须进行更改才能在清单中集成 /app1/ 前缀。在构建时获得正确的 style/content url。 ;)

例如使用 Symfony Encore

来自这个:

// directory where compiled assets will be stored
.setOutputPath('public/build/')
// public path used by the web server to access the output path
.setPublicPath('/build')
// only needed for CDN's or sub-directory deploy
//.setManifestKeyPrefix('build/')

对此:

// directory where compiled assets will be stored
.setOutputPath('public/build/')
// public path used by the web server to access the output path
.setPublicPath('/app1/build')
// only needed for CDN's or sub-directory deploy
.setManifestKeyPrefix('build/')

感谢阅读 :)

如果有什么我应该补充的以便更好地理解,请评论;)