php - 使用 Varnish 时修改路由和 url
问题描述
我有一个项目,在 Slim 4 项目之前使用了 Varnish。由于某些项目的特殊性,应隐藏原始 url,并将传入请求重写为其他一些标头。
例子
- 对 demo.xyz 的原始调用即将来到 Varnish
- Varnish 将请求转换为
http://slimapp.dev/url/demo.xyz
- 原始主机保存在标头中
X-Orig-Host: demo.xyz
Slim App 需要检测它是否是 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 对象,但我不知道如何。
- 为 Twig-View 写一个 TwigExtension 来修改方法
url_for
等等。
第一个想法感觉更可靠,也是正确的地方。另一个意味着我需要覆盖辅助方法来构建基于X-Orig-Host
.
知道如何修改 Uri / 可能覆盖该create
方法吗?
提前致谢!
PS:我在Slim Discourse中提出的问题相同。
更新 1
路由.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');
});
};
中间件.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}
解决方案
您可以像这样实现自己的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());
要在 Twig 模板中输出完整的 url,请使用该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(...)
推荐阅读
- amazon-web-services - 如何监控用户对 AWS S3 的访问?
- google-sheets - Google 表格中 INDIRECT 函数的奇怪行为。仅在剪切和粘贴后有效
- regex - pgrep 多个进程名称
- npm - 修复 Vs Code Server 找不到模块错误
- json - 使用 Python3 抓取 JSON 网格数据
- ios - 在 iOS 13.1 中从 SceneDelegate 设置 RootViewController 时,UIElements 变为非活动状态
- matrix - 如何在没有模块的情况下在 OCAML 中将 2 个矩阵相加?
- unit-testing - 您是否在代码覆盖率中包含测试文件?
- python - 查找 Tensorflow 操作的输入张量
- azure - Azure Policy VM 备份 DeployIfNotExist PolicyEvaluationRetriesExceeded