如何解决在子目录中使用反向代理运行Symfony 5
我喜欢在提供以下端点的反向代理后面运行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”路径前缀。
解决方法
正确的做法(示例):
创建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
所有控制器现在都可以通过以下网址获得:
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.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);
}
}
所有控制器现在都可以通过以下网址获得:
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()
);
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。