하위 디렉토리에서 역방향 프록시를 사용하여 Symfony 5 실행

Aug 21 2020

다음 엔드 포인트를 제공하는 리버스 프록시 뒤에서 Symfony 5 애플리케이션을 실행하고 싶습니다.

https://my.domain/service1/

프록시 구성은 기본적으로 다음과 같습니다.

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

역방향 프록시가 연결되는 서버에서 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

이제 내 질문은 생성 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()
            );
        }
    }

}