サブディレクトリでリバースプロキシを使用してSymfony5を実行する

Aug 21 2020

次のエンドポイントを提供するリバースプロキシの背後でSymfony5アプリケーションを実行するのが好きです。

https://my.domain/service1/

プロキシ設定は基本的にこれです:

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

リバースプロキシが接続しているサーバーで、Symfonyアプリケーションを提供するために次のapacheルールを使用します。

<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」パスプレフィックスを処理できません。

たとえば、下のプロファイラーにアクセスしようとします https://my.domain/_wdt/8e3926 の代わりに https://my.domain/service1/_wdt/8e3926 ルートルートの横では、すべてのルーティングが機能していません。

例:アクセスしようとすると https://my.domain/service1/my/page にリダイレクトされます https://my.domain/my/page

今私の質問は、生成URLセットのときに「service1」パスプレフィックスを知るようにSymfonyを設定するにはどうすればよいですか。

回答

4 Jimmix Sep 29 2020 at 11:35

それを行う適切な方法(例):

作成する 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-その内容を削除して、次のように入力します。

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

すべてのコントローラーがURLで利用できるようになりました。

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ようにする場合は、次のように編集します。

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

これで、アノテーションを介して行われるルートにプレフィックスが追加されます。

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

いくつかの参考文献:

symfonyルーティングプレフィックス
Symfonyルーティング設定キー

service1すべてのルーティングにプレフィックスを追加するためのプレフィックスの迅速で汚い回避策を追加します(非推奨)。

上記のようにルーティングを変更する代わりに、編集するだけです src/Kernel.php protected function configureRoutes

最後に$routes->import追加->prefix('service1')してすべての行を変更し、次のように表示します。

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);
    }
}

すべてのコントローラーがURLで利用できるようになりました。

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
1 Johni Oct 05 2020 at 19:55

@Jimmixが提供するソリューションに加えて、リクエストパスにプレフィックスを追加するサブスクライバーを作成する必要がありました。

<?php namespace My\Bundle\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;

class AppPrefixSubscriber implements EventSubscriberInterface {

    /** @var string */
    private $appPrefix; public function __construct(?string $appPrefix) {
        $this->appPrefix = $appPrefix;
    }

    /**
     * Returns events to subscribe to
     *
     * @return array
     */
    public static function getSubscribedEvents() {
        return [
            KernelEvents::REQUEST => [
                ['onKernelRequest', 3000]
            ]
        ];
    }

    /**
     * Adds base url to request based on environment var
     *
     * @param RequestEvent $event */ public function onKernelRequest(RequestEvent $event) {
        if (!$event->isMasterRequest()) { return; } if ($this->appPrefix) {
            $request = $event->getRequest();

            $newUri = $this->appPrefix .
                $request->server->get('REQUEST_URI'); $event->getRequest()->server->set('REQUEST_URI', $newUri); $request->initialize(
                $request->query->all(), $request->request->all(),
                $request->attributes->all(), $request->cookies->all(),
                $request->files->all(), $request->server->all(),
                $request->getContent()
            );
        }
    }

}