【问题标题】:Running Symfony 5 with reverse proxy in subdirectory在子目录中使用反向代理运行 Symfony 5
【发布时间】:2020-08-21 09:20:11
【问题描述】:

我喜欢在提供以下端点的反向代理后面运行 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 在生成 url 时了解“service1”路径前缀。

【问题讨论】:

  • 你必须在 app/app_dev.php 和 composer json refactory-project.com/2015/11/30/…进行一些编辑
  • symfony 应用程序不在子文件夹中,这个附加目录是反向代理引入的。

标签: php symfony


【解决方案1】:

正确的做法(示例):

创建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

现在所有的控制器都可以在 urls 上使用:

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 Routing Prefix
Symfony Routing Configuration Keys

添加前缀快速而肮脏的解决方法,为所有路由添加前缀service1(不推荐)。

无需像上面那样更改路由,只需编辑src/Kernel.phpprotected function configureRoutes

并通过在末尾添加 -&gt;prefix('service1') 来更改每个 $routes-&gt;import 行,使其看起来像这样:

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

现在所有的控制器都可以在 urls 上使用:

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

【讨论】:

  • 基于注解的路由是否也可以添加一个公共前缀(在代码或配置文件中的某个位置,而不是在注解本身中)?
  • @Johni 是的,请参阅Adding prefix for annotations 部分下的更新答案
  • 感谢它现在有效。我还添加了一个内核请求订阅者来将前缀添加到请求 url,因为这不是由反向代理转发的。
  • @Johni 很高兴能帮上忙。您能否编辑您的问题并将该订阅者添加为附加解决方案,以便将来遇到相同问题的所有其他人都可以进行完整的示例修改?
【解决方案2】:

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

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-08
    • 1970-01-01
    • 2020-08-21
    • 1970-01-01
    • 1970-01-01
    • 2019-12-22
    • 2018-12-15
    • 1970-01-01
    相关资源
    最近更新 更多