Измените маршруты и URL-адрес при использовании Varnish
У меня есть проект, в котором Varnish используется перед проектом Slim 4. Из-за некоторых особенностей проекта исходный URL-адрес должен быть скрыт, а входящий запрос переписан на некоторые другие заголовки.
пример
- Оригинальный вызов demo.xyz прибывает в Varnish
- Varnish преобразует запрос в
http://slimapp.dev/url/demo.xyz
- Исходный хост сохраняется в заголовке с
X-Orig-Host: demo.xyz
Приложение Slim должно определить, является ли это запросом Varnish (я уже получил его), и преобразовать маршруты.
Маршруты
Без лака:
$app->group('/url/{url}', function (RouteCollectorProxy $group) {
$group->get('[/city/{city}]', IndexAction::class)->setName('home');
$group->get('/search[/{query}]', SearchQueryAction::class)->setName('search-query');
});
С лаком:
$app->get('[/city/{city}]', IndexAction::class)->setName('home');
$app->get('/search[/{query}]', SearchQueryAction::class)->setName('search-query');
Поэтому при создании маршрута с url_for
( Пакет Twig-View) URL-адреса должны быть сгенерированы следующим образом:
- Маршрут без лака:
http://slimapp.dev/url/demo.xyz/article/123
- Маршрут с лаком:
http://demo.xyz/article/123
Идеи:
- Измените исходный объект UriInterface, но я понятия не имею, как это сделать.
- Напишите TwigExtension для Twig-View, чтобы изменить методы для
url_for
и так далее.
Первые идеи кажутся более надежными и правильными. Другой будет означать, что мне нужно будет перезаписать вспомогательные методы для создания URL-адреса на основеX-Orig-Host
.
Любая идея, как я могу изменить Uri /, вероятно, перезаписать create
метод?
Заранее спасибо!
PS: Те же вопросы, что я задавал в Slim Discourse.
ОБНОВЛЕНИЕ 1
routes.php
return function (App $app) {
$app->get('/', function () {
die('No URL defined.');
})->setName('root');
$app->group('/url/{url}', function (RouteCollectorProxy $group) {
$group->get('[/city/{city}]', IndexAction::class)->setName('home');
# Internal page search
$group->get('/search[/{query}]', SearchQueryAction::class)->setName('search-query');
});
};
middleware.php
return function(App $app) {
$c = $app->getContainer();
$app->addBodyParsingMiddleware();
$app->add(TwigMiddleware::class);
$app->addRoutingMiddleware();
$app->add(VarnishBasePathMiddleware::class);
$displayErrorDetails = $c->get(Configuration::class)->getBool('displayErrorDetails');
$errorMiddleware = $app->addErrorMiddleware($displayErrorDetails, false, false);
$errorHandler = $errorMiddleware->getDefaultErrorHandler();
$errorHandler->registerErrorRenderer('text/html', HtmlErrorRenderer::class);
$errorHandler->registerErrorRenderer('application/json', JsonErrorRenderer::class);
};
Сообщение об ошибке
[404] Not found. in /usr/share/nginx/html/vendor/slim/slim/Slim/Middleware/RoutingMiddleware.php on line 91.
Backtrace: #0 /usr/share/nginx/html/vendor/slim/slim/Slim/Middleware/RoutingMiddleware.php(57): Slim\Middleware\RoutingMiddleware->performRouting(Object(Slim\Psr7\Request)) #1 /usr/share/nginx/html/vendor/slim/slim/Slim/MiddlewareDispatcher.php(132): Slim\Middleware\RoutingMiddleware->process(Object(Slim\Psr7\Request), Object(class@anonymous)) #2 /usr/share/nginx/html/src/Middleware/VarnishBasePathMiddleware.php(28): class@anonymous->handle(Object(Slim\Psr7\Request)) #3 /usr/share/nginx/html/vendor/slim/slim/Slim/MiddlewareDispatcher.php(180): App\Middleware\VarnishBasePathMiddleware->process(Object(Slim\Psr7\Request), Object(class@anonymous)) #4 /usr/share/nginx/html/vendor/slim/twig-view/src/TwigMiddleware.php(125): class@anonymous->handle(Object(Slim\Psr7\Request)) #5 /usr/share/nginx/html/vendor/slim/slim/Slim/MiddlewareDispatcher.php(180): Slim\Views\TwigMiddleware->process(Object(Slim\Psr7\Request), Object(class@anonymous)) #6 /usr/share/nginx/html/vendor/slim/slim/Slim/Middleware/ErrorMiddleware.php(89): class@anonymous->handle(Object(Slim\Psr7\Request)) #7 /usr/share/nginx/html/vendor/slim/slim/Slim/MiddlewareDispatcher.php(132): Slim\Middleware\ErrorMiddleware->process(Object(Slim\Psr7\Request), Object(class@anonymous)) #8 /usr/share/nginx/html/vendor/slim/slim/Slim/MiddlewareDispatcher.php(73): class@anonymous->handle(Object(Slim\Psr7\Request)) #9 /usr/share/nginx/html/vendor/slim/slim/Slim/App.php(208): Slim\MiddlewareDispatcher->handle(Object(Slim\Psr7\Request)) #10 /usr/share/nginx/html/public/index.php(57): Slim\App->handle(Object(Slim\Psr7\Request)) #11 {main}
1 ответ
Вы можете реализовать свои собственные ServerRequestCreatorInterface
класс вроде этого:
use Psr\Http\Message\ServerRequestInterface;
use Slim\Factory\ServerRequestCreatorFactory;
use Slim\Interfaces\ServerRequestCreatorInterface;
use Slim\Psr7\Factory\ServerRequestFactory;
class VarnishServerRequestCreator implements ServerRequestCreatorInterface
{
public function createServerRequestFromGlobals(): ServerRequestInterface
{
$request = ServerRequestFactory::createFromGlobals();
$serverParams = $request->getServerParams();
if (isset($serverParams['X-Orig-Host'])) {
// Replace the hostname
$uri = $request->getUri()->withHost($serverParams['X-Orig-Host']);
$request = $request->withUri($uri);
}
return $request;
}
}
ServerRequestCreatorFactory::setServerRequestCreator(new VarnishServerRequestCreator());
Чтобы вывести полный URL-адрес в ваших шаблонах Twig, используйте full_url_for
функция. Пример:
{{ full_url_for('article') }}
Выход:
https://demo.xyz/article
Чтобы изменить базовый путь, вы можете добавить это специальное промежуточное ПО:
<?php
namespace App\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Slim\App;
final class VarnishBasePathMiddleware implements MiddlewareInterface
{
/**
* @var App The slim app
*/
private $app;
public function __construct(App $app)
{
$this->app = $app;
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$serverParams = $request->getServerParams();
// Detect Varnish
if (isset($serverParams['X-Orig-Host'])) {
// Change the base path
$this->app->setBasePath('/url/demo.xyz');
}
return $handler->handle($request);
}
}
В VarnishBasePathMiddleware
необходимо добавить после RoutingMiddleware
$app->add(TwigMiddleware::class);
$app->addRoutingMiddleware();
$app->add(\App\Middleware\VarnishBasePathMiddleware::class); // <--- here
$app->addErrorMiddleware(...)