#php #symfony
#php #symfony
Вопрос:
Мне нравится запускать приложение Symfony 5 за обратным прокси, который предоставляет следующую конечную точку:
Конфигурация прокси в основном такая:
ProxyPass /marketsy/ http://internal.service1/
На сервере, к которому подключается обратный прокси, я использую следующее правило apache для обслуживания моего приложения Symfony:
<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
Теперь мой вопрос в том, как я могу настроить Symfony так, чтобы он знал о префиксе пути «service1» при генерации URL-адресов ets.
Комментарии:
1. вам нужно внести некоторые изменения в app/app_dev.php и composer json refactory-project.com/2015/11/30 /…
2. Приложение symfony на самом деле не находится во вложенной папке, этот дополнительный каталог вводится обратным прокси.
Ответ №1:
Правильный способ сделать это (пример):
Создать src/Controller/BarController.php
<?php
namespace AppController;
use SymfonyComponentHttpFoundationResponse;
class BarController
{
public function index()
{
return new Response('<p>Bar controler response</p>');
}
}
и src/Controller/FooController.php
<?php
namespace AppController;
use SymfonyComponentHttpFoundationResponse;
class FooController
{
public function index()
{
return new Response('<p>Foo controler response</p>');
}
}
Создать config/routes/prefix-routes.yaml
index:
path: /
controller: AppControllerDefaultController::index
bar:
path: /bar
controller: AppControllerBarController::index
foo:
path: /foo
controller: AppControllerFooController::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 AppController;
use SymfonyComponentRoutingAnnotationRoute;
use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentHttpFoundationResponse;
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. Возможно ли также, чтобы маршруты на основе аннотаций добавляли общий префикс (где-нибудь в коде или файле конфигурации, а не в самой аннотации)?
2. @Johni Да, пожалуйста, смотрите обновленный ответ в разделе
Adding prefix for annotations
3. Спасибо, теперь это работает. Я также добавил подписчика запроса ядра для добавления префикса к URL запроса, поскольку он не пересылается обратным прокси.
4. @Johni Я рад, что смог помочь. Не могли бы вы, пожалуйста, отредактировать свой вопрос и добавить этого подписчика в качестве дополнительного решения, чтобы у всех остальных в будущем, имеющих ту же проблему, был полный набор примеров изменений, которые нужно выполнить?
Ответ №2:
В дополнение к решению, предоставленному @Jimmix, мне пришлось написать подписчика, чтобы добавить префикс к моему пути запроса:
<?php namespace MyBundleEventSubscriber;
use SymfonyComponentEventDispatcherEventSubscriberInterface;
use SymfonyComponentHttpKernelEventRequestEvent;
use SymfonyComponentHttpKernelKernelEvents;
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()
);
}
}
}