[英]Running Symfony 5 with reverse proxy in subdirectory
我喜歡在提供以下端點的反向代理后面運行 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 以了解生成 url 時的“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
並編輯 routing 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
為注解添加前綴:
創建 controller 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
一些參考資料:
添加前綴快速而骯臟的解決方法以將前綴service1
添加到所有路由(不推薦)。
而不是像上面那樣更改路由,只需編輯src/Kernel.php
protected function configureRoutes
並通過在末尾添加->prefix('service1')
來更改每個$routes->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
除了@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()
);
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.