サブディレクトリでリバースプロキシを使用してSymfony5を実行する
次のエンドポイントを提供するリバースプロキシの背後で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を設定するにはどうすればよいですか。
回答
それを行う適切な方法(例):
作成する 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
@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()
);
}
}
}