webgriffe / cgi-http-kernel
从 HttpKernelInterface 到 CGI 的适配器。最初是 igorw/cgi-http-kerl,现已废弃。
Requires
- symfony/http-kernel: ~2.1
- symfony/process: ~2.1
Requires (Dev)
- silex/silex: 1.0.*@dev
README
从 HttpKernelInterface 到 CGI 的适配器。
HttpKernelInterface 是一个谎言
你认为你需要重写整个应用程序以使用 HttpFoundation 来利用 HttpKernelInterface 的功能测试吗?
然而,事实并非如此。一些非常聪明的人提出了一个叫做 CGI(通用网关接口)的东西,它定义了 Web 服务器和 Web 应用程序之间的接口。它很棒,因为它使用 UNIX 管道进行通信,这意味着它也很容易假装成 Web 服务器,只需手动通过命令行调用应用程序并传递任何输入和环境变量。
在 PHP 中,这可以通过使用随 PHP 分发几乎每个 PHP 分发一起提供的 php-cgi
来实现。在命令行上调用它的最基本方法是
$ php-cgi hello.php
如果你想知道如何进行更高级的操作,请阅读该 CGI 规范。
那么这与 HttpKernelInterface 有什么关系呢?CGI 和该接口几乎做了同样的事情,它们抽象了 Web 服务器和应用程序之间的通信。内核接口在 PHP 中这样做,而 CGI 以一种与语言无关的方式这样做。
CgiHttpKernel 在这两个接口之间进行转换。作为库的用户,你就像它是一个真正的 HttpKernelInterface 应用程序一样与之交互,但实际上它将在后台实际在命令行上调用 php-cgi
,解析输出,并返回一个 Response
实例。
例如
$kernel = new CgiHttpKernel(__DIR__.'/../phpBB'); $request = Request::create('/index.php'); $response = $kernel->handle($request); var_dump($response->getContent());
如果你想让所有请求都通过一个前端控制器,可以向构造函数传递第二个参数。
$kernel = new CgiHttpKernel(__DIR__.'/../web', 'app.php'); $request = Request::create('/foo'); $response = $kernel->handle($request);
你还可以设置 php-cgi 可执行文件的路径和一个进程超时时间(默认设置为 60 秒)
$kernel = new CgiHttpKernel(__DIR__.'/../web', 'app.php', '/path/to/php-cgi', 300); // Or set the timeout to null to disable the timeout at all $kernel = new CgiHttpKernel(__DIR__.'/../web', 'app.php', '/path/to/php-cgi', null);
然而,真正的力量来自使用与 HttpKernelInterface 集成的库,例如 Symfony\Component\HttpKernel\Client
。
$kernel = new CgiHttpKernel(__DIR__.'/../phpBB'); $client = new Client($kernel); $crawler = $client->request('GET', '/index.php'); $this->assertGreaterThan(0, $crawler->filter('.topiclist')->count());
它真的是一个谎言吗?
其实并不是。CgiHttpKernel 只适用于功能测试,因为它相当慢。它之所以慢,是因为它必须为每个请求启动一个新的进程。这也是一些非常聪明的人提出了类似 CGI 但更快的 FastCGI 的原因。
FastCGI 允许应用程序启动一个长时间运行的进程,该进程监听端口,因此无需进程启动开销。在 PHP 领域,这通常由 PHP-FPM(即 FastCGI 进程管理器)管理。
FastCGI 适用于生产,但不太适合测试,因为它需要在单独的进程中运行,监听端口,需要配置等。
然而,有一个 FcgiHttpKernel 将此项目的想法移植到 FastCGI。它实际上可能对测试很有用。
何时使用 CgiHttpKernel?
它主要用于编写旧应用程序的功能测试。这可能会让你在不太可能破坏现有代码的情况下重构旧代码。
祝你好运。
具体细节
属性
请求属性会被序列化并通过 SYMFONY_ATTRIBUTES
环境变量提供给目标脚本。这意味着它可以通过以下方式获取原始属性
$attributes = unserialize($_SERVER['SYMFONY_ATTRIBUTES']);