webgriffe/cgi-http-kernel

从 HttpKernelInterface 到 CGI 的适配器。最初是 igorw/cgi-http-kerl,现已废弃。

v1.1.0 2017-03-29 10:05 UTC

This package is auto-updated.

Last update: 2024-09-07 21:14:34 UTC


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']);