在子目录中使用反向代理运行 Symfony 5

问题描述:

我喜欢在提供以下端点的反向代理后面运行 Symfony 5 应用程序:

I like to run a Symfony 5 application behind a reverse proxy which supplies the following endpoint:

https://my.domain/service1/

代理配置基本上是这样的:

The proxy config basically is this:

ProxyPass /marketsy/ http://internal.service1/

在反向代理连接到的服务器上,我使用以下 apache 规则为我的 Symfony 应用程序提供服务:

On the server the reverse proxy is connecting to, I use the following apache rule for serving my Symfony application:

<VirtualHost *:80>
  ServerName internal.service1
  DocumentRoot /webroot/service1/public

 <FilesMatch \.php$>
     SetHandler proxy:unix:/run/php/php7.2-fpm-ui.sock|fcgi://localhost
     SetEnvIfNoCase ^Authorization$ "(.+)" HTTP_AUTHORIZATION=$1
     SetEnv HTTP_X_FORWARDED_PROTO "https"
 </FilesMatch>

 <Directory  /webroot/service1/public>
     AllowOverride None
     Require all granted
     FallbackResource /index.php
 </Directory>

 <Directory  /webroot/service1/public/bundles>
     FallbackResource disabled
 </Directory>
</VirtualHost>

应用程序本身是可重新访问的,但 Symfony 无法处理service1"路径前缀.

The application itself is reqachable but Symfony can't hanle the "service1" path prefix.

例如,它尝试访问 https://my.domain/_wdt/8e3926 下的分析器而不是 https://my.domain/service1/_wdt/8e3926 和根路由旁边的所有路由不工作:

For example it tries to access the profiler under https://my.domain/_wdt/8e3926 instead of https://my.domain/service1/_wdt/8e3926 and beside the root route all the routing isn't working:

例如:当我尝试访问 https://my.domain/service1/my/page 我会得到重定向到 https://my.domain/my/page

For example: When I try to access https://my.domain/service1/my/page i will get redirected to https://my.domain/my/page

现在我的问题是,我如何配置 Symfony 以了解service1"?生成url时的路径前缀.

Now my question is, how can I configure Symfony to know about the "service1" path prefix when generation urls ets.

正确的做法(示例):

创建src/Controller/BarController.php

<?php

namespace App\Controller;

use Symfony\Component\HttpFoundation\Response;

class BarController
{
    public function index()
    {
        return new Response('<p>Bar controler response</p>');
    }
}

src/Controller/FooController.php

<?php

namespace App\Controller;

use Symfony\Component\HttpFoundation\Response;

class FooController
{
    public function index()
    {
        return new Response('<p>Foo controler response</p>');
    }
}

创建config/routes/prefix-routes.yaml

index:
    path: /
    controller: App\Controller\DefaultController::index

bar:
    path: /bar
    controller: App\Controller\BarController::index
 
foo:
    path: /foo
    controller: App\Controller\FooController::index
 

并编辑路由 config/routes.yaml - 删除其内容,然后将:

and edit routing config/routes.yaml - delete its contents and just put:

prefixed:
   resource: "routes/prefix-routes.yaml"
   prefix: service1

所有控制器现在都可以在 urls 上找到:

all of controllers are now available at urls:

http://localhost/service1/ for DefaultController.php
http://localhost/service1/bar for BarController.php
http://localhost/service1/foo for FooController.php

如果您希望您的分析器也使用 service1 前缀,请按以下方式编辑 config/routes/dev/web_profiler.yaml:

If you want your profiler to work with service1 prefix as well then edit config/routes/dev/web_profiler.yaml this way:

web_profiler_wdt:
    resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml'
    prefix: service1/_wdt

web_profiler_profiler:
    resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml'
    prefix: service1/_profiler

现在它们应该可以在:

http://localhost/service1/_wdt... for wdt
http://localhost/service1/_profiler for profiler

为注解添加前缀:

创建控制器src/Controller/AnnoController.php:

<?php

namespace App\Controller;

use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;

class AnnoController extends AbstractController
{
    /**
     * @Route("/anno", name="anno")
     */
    public function index()
    {
        return new Response('<p>Anno controler response</p>');
    }
}

编辑 config/routes/annotations.yaml 并添加 prefix: service1:

controllers:
    resource: ../../src/Controller/
    type: annotation
    prefix: service1

kernel:
    resource: ../../src/Kernel.php
    type: annotation

现在前缀添加到通过注释完成的路由:

Now prefix is added to routes done via annotation:

http://localhost/service1/anno for AnnoController.php

一些参考:

Symfony 路由前缀
Symfony 路由配置键

添加前缀快速而肮脏的解决方法,将前缀 service1 添加到所有路由(不推荐).

Adding prefix quick and dirty workaround to add prefix service1 to all of routing (not recommended).

不要像上面那样改变路由,只需编辑 src/Kernel.php protected function configureRoutes

Instead of changing routing as above just Edit src/Kernel.php protected function configureRoutes

并通过在末尾添加 ->prefix('service1') 来更改每个 $routes->import 行,使其看起来像这样:

and change every $routes->import line by adding ->prefix('service1') at the end so it looks this way:

protected function configureRoutes(RoutingConfigurator $routes): void
{
    $routes->import('../config/{routes}/'.$this->environment.'/*.yaml')->prefix('service1');
    $routes->import('../config/{routes}/*.yaml')->prefix('service1');

    if (is_file(\dirname(__DIR__).'/config/routes.yaml')) {

        $routes->import('../config/{routes}.yaml')->prefix('service1');

    } elseif (is_file($path = \dirname(__DIR__).'/config/routes.php')) {
        (require $path)($routes->withPath($path), $this);
    }
}

所有控制器现在都可以在 urls 上找到:

all of controllers are now available at urls:

http://localhost/service1/ for DefaultController.php
http://localhost/service1/bar for BarController.php
http://localhost/service1/foo for FooController.php

以及分析器:

http://localhost/service1/_wdt... for wdt
http://localhost/service1/_profiler for profiler