Запуск Symfony 5 с обратным прокси в подкаталоге

#php #symfony

#php #symfony

Вопрос:

Мне нравится запускать приложение Symfony 5 за обратным прокси, который предоставляет следующую конечную точку:

https://my.domain/service1/

Конфигурация прокси в основном такая:

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

}