phly / http
Requires
- php: >=5.4.8
- psr/http-message: ~1.0
Requires (Dev)
- phpunit/phpunit: ~4.6
- squizlabs/php_codesniffer: ~2.0
Provides
- psr/http-message-implementation: ~1.0.0
README
废弃!或者,更确切地说,重新命名!
phly/http已迁移到zendframework组织,作为zend-diactoros(Diactoros,字面意为“使者”,赫耳墨斯的别称)。
请使用该包,并针对它提交问题和拉取请求。我已关闭针对phly/http的问题和拉取请求。
phly/http
是一个PHP包,包含已接受的PSR-7 HTTP消息接口的实现,以及类似于node的http.Server的“服务器”实现。
该包存在
- 为了提供有关服务器端应用的PSR HTTP消息接口的证明概念。
- 为了提供一个类似Node的范式用于PHP前端控制器。
- 为了提供一个将请求从服务器环境封送的方法。
安装和需求
使用composer安装此库
$ composer require phly/http
phly/http
有以下依赖(由Composer管理)
psr/http-message
,它定义了HTTP消息的接口,包括请求和响应。phly/http
为每个这些接口提供了实现。
用法
用法将根据您是编写HTTP客户端还是服务器端应用而有所不同。
对于HTTP客户端,您将创建并填充一个Request
实例,客户端应返回一个Response
实例。
对于服务器端应用,您将创建一个ServerRequest
实例,填充并返回一个Response
实例。
HTTP客户端
客户端将发送请求并返回响应。作为开发者,您将创建和填充请求,然后检查响应。请求和响应都是不可变的;如果您进行更改(例如,通过调用setter方法),您必须捕获返回值,因为它是一个新实例。
// Create a request $request = (new Phly\Http\Request()) ->withUri(new Phly\Http\Uri('http://example.com')) ->withMethod('PATCH') ->withAddedHeader('Authorization', 'Bearer ' . $token) ->withAddedHeader('Content-Type', 'application/json'); // OR: $request = new Phly\Http\Request( 'http://example.com', 'PATCH', 'php://memory', [ 'Authorization' => 'Bearer ' . $token, 'Content-Type' => 'application/json', ] ); // If you want to set a non-origin-form request target, set the // request-target explicitly: $request = $request->withRequestTarget((string) $uri)); // absolute-form $request = $request->withRequestTarget($uri->getAuthority()); // authority-form $request = $request->withRequestTarget('*'); // asterisk-form // Once you have the instance: $request->getBody()->write(json_encode($data)); $response = $client->send($request); printf("Response status: %d (%s)\n", $response->getStatusCode(), $response->getReasonPhrase()); printf("Headers:\n"); foreach ($response->getHeaders() as $header => $values) { printf("%s: %s\n", $header, implode(', ', $values)); } printf("Message:\n%s\n", $response->getBody());
(注意:phly/http不提供客户端实现;上面只是一个可能的实现示例。)
服务器端应用
服务器端应用需要根据超全局变量封送传入的请求,然后填充并发送响应。
封送传入请求
PHP包含大量关于传入请求的信息,并将这些信息保存在多个位置。Phly\Http\ServerRequestFactory::fromGlobals()
可以将这些信息简化为请求实例。
您可以用以下顺序调用工厂方法,带或不带以下参数
$server
,通常为$_SERVER
$query
,通常为$_GET
$body
,通常为$_POST
$cookies
,通常为$_COOKIE
$files
,通常为$_FILES
该方法将返回一个 Phly\Http\ServerRequest
实例。如果省略任何参数,将使用相应的超级全局变量。
$request = Phly\Http\ServerRequestFactory::fromGlobals( $_SERVER, $_GET, $_POST, $_COOKIE, $_FILES );
响应操作
使用响应对象添加头部信息并提供响应内容。向主体写入不创建响应状态变化,因此可以不捕获返回值即可完成。但操作头部信息时则会。
$response = new Phly\Http\Response(); // Write to the response body: $response->getBody()->write("some content\n"); // Multiple calls to write() append: $response->getBody()->write("more content\n"); // now "some content\nmore content\n" // Add headers // Note: headers do not need to be added before data is written to the body! $response = $response ->withHeader('Content-Type', 'text/plain') ->withAddedHeader('X-Show-Something', 'something');
“服务”一个应用
Phly\Http\Server
模拟了 node 的 http.Server
类的部分 API。它调用一个回调,将 ServerRequest
、Response
以及可选的用于不完整/未处理的请求的回调传递给该回调。
您可以通过以下三种方式之一创建服务器
// Direct instantiation, with a callback handler, request, and response $server = new Phly\Http\Server( function ($request, $response, $done) { $response->getBody()->write("Hello world!"); }, $request, $response ); // Using the createServer factory, providing it with the various superglobals: $server = Phly\Http\Server::createServer( function ($request, $response, $done) { $response->getBody()->write("Hello world!"); }, $_SERVER, $_GET, $_POST, $_COOKIE, $_FILES ); // Using the createServerFromRequest factory, and providing it a request: $server = Phly\Http\Server::createServerfromRequest( function ($request, $response, $done) { $response->getBody()->write("Hello world!"); }, $request );
服务器回调可以期望最多三个参数,顺序如下
$request
- 请求对象$response
- 响应对象$done
- 当完成时可选的回调
一旦您拥有服务器实例,您必须指导它进行监听
$server->listen();
此时,您可以可选地向 listen()
提供一个回调;这将作为第三个参数($done
)传递给处理器
$server->listen(function ($request, $response, $error = null) { if (! $error) { return; } // do something with the error... });
通常,listen
回调将是一个错误处理器,并可以期望接收请求、响应和错误作为其参数(尽管错误可能为 null)。
API
请求消息
Phly\Http\Request
实现 Psr\Http\Message\RequestInterface
,旨在用于客户端请求。它包括以下方法
class Request { public function __construct( $uri = null, $method = null, $body = 'php://memory', array $headers = [] ); // See psr/http-message's RequestInterface for other methods }
请求是不可变的。任何会改变状态的方法(以 with
和 without
为前缀的)都会返回一个具有所需更改的新实例。
服务器请求消息
对于服务器端应用,Phly\Http\ServerRequest
实现 Psr\Http\Message\ServerRequestInterface
,它提供了访问 HTTP 请求元素以及访问传入数据的各个元素的一致访问方式。包括以下方法
class ServerRequest { public function __construct( array $serverParams = [], array $fileParams = [], $uri = null, $method = null, $body = 'php://input', array $headers = [] ); // See psr/http-message's ServerRequestInterface for other methods. }
ServerRequest
是不可变的。任何会改变状态的方法(以 with
和 without
为前缀的)都会返回一个具有所需更改的新实例。然而,服务器参数被认为是完全不可变的,因为它们不能被重新计算,而是作为其他值的来源。
响应消息
Phly\Http\Response
提供了 Psr\Http\Message\ResponseInterface
的实现,这是一个用于聚合响应信息的对象,用于 HTTP 客户端和服务器端应用,包括头部信息和消息主体内容。包括以下内容
class Response { public function __construct( $body = 'php://memory', $statusCode = 200, array $headers = [] ); // See psr/http-message's ResponseInterface for other methods }
与 Request
和 ServerRequest
类似,响应也是不可变的。任何会改变状态的方法(以 with
和 without
为前缀的)都会返回一个具有所需更改的新实例。
ServerRequestFactory
这个静态类可以用来从PHP环境中序列化一个ServerRequest
实例。主要的入口点是Phly\Http\ServerRequestFactory::fromGlobals(array $server, array $query, array $body, array $cookies, array $files)
。该方法将创建一个包含提供数据的新的ServerRequest
实例。使用示例包括
// Returns new ServerRequest instance, using values from superglobals: $request = ServerRequestFactory::fromGlobals(); // or // Returns new ServerRequest instance, using values provided (in this // case, equivalent to the previous!) $request = RequestFactory::fromGlobals( $_SERVER, $_GET, $_POST, $_COOKIE, $_FILES );
URI
Phly\Http\Uri
是Psr\Http\Message\UriInterface
的实现,用于建模和验证URI。它实现了__toString()
,允许它被表示为字符串并直接通过echo()
输出。以下方法相关
class Uri { public function __construct($uri = ''); // See psr/http-message's UriInterface for other methods. }
与各种消息对象一样,URI是不可变的。任何会改变状态的方法(那些以with
和without
开头的方法)都返回一个新的实例,该实例包含所请求的更改。
流
Phly\Http\Stream
是Psr\Http\Message\StreamInterface
的实现,提供了一系列操作组合PHP流资源的功能。构造函数接受一个流,可以是以下之一
- 一个流标识符;例如,
php://input
,一个文件名等。 - 一个PHP流资源
如果提供了一个流标识符,还可以提供一个可选的第二个参数,即通过fopen
打开流时使用的文件模式。
ServerRequest
对象默认使用只读的php://input
流;Response
对象默认使用php://memory
,模式为wb+
,允许二进制读写访问。
在大多数情况下,你不会直接与流对象交互。
上传文件
Phly\Http\UploadedFile
是Psr\Http\Message\UploadedFileInterface
的实现,提供了一种对单个上传文件的抽象,包括与它作为流交互或将其移动到文件系统位置的行为。
在大多数情况下,你只会使用在UploadedFileInterface
中定义的方法。
服务器
Phly\Http\Server
表示一个能够执行回调的服务器。它有四个方法
class Server { public function __construct( callable $callback, Psr\Http\Message\ServerRequestInterface $request, Psr\Http\Message\ResponseInterface $response ); public static function createServer( callable $callback, array $server, // usually $_SERVER array $query, // usually $_GET array $body, // usually $_POST array $cookies, // usually $_COOKIE array $files // usually $_FILES ); public static function createServerFromRequest( callable $callback, Psr\Http\Message\ServerRequestInterface $request, Psr\Http\Message\ResponseInterface $response = null ); public function setEmitter(Response\EmitterInterface $emitter); public function listen(callable $finalHandler = null); }
你可以使用构造函数、createServer()
或createServerFromRequest()
方法中的任何一个来创建一个Server
实例。如果你希望使用默认的请求和响应实现,createServer($middleware, $_SERVER, $_GET, $_POST, $_COOKIE, $_FILES)
是推荐的选择,因为这个方法还将根据PHP请求环境序列化ServerRequest
对象。如果你希望使用自己的实现,将它们传递给构造函数或createServerFromRequest()
方法(后者将创建一个默认的Response
实例,如果你省略它)。
listen()
执行回调。如果提供了$finalHandler
,它将被作为第三个参数传递给服务器上注册的$callback
。
发出响应
如果你使用的是非SAPI的PHP实现,并希望使用Server
类,或者你不希望使用Server
实现但想发出响应,这个包提供了一个接口Phly\Http\Response\EmitterInterface
,定义了一个用于发出响应的emit()
方法。目前有一个实现,Phly\Http\Response\SapiEmitter
,它将使用原生的PHP函数header()
和echo
来发出响应。如果你使用的是非SAPI实现,你需要创建自己的EmitterInterface
实现。
序列化
有时,创建消息的字符串表示(序列化),或将字符串或流消息转换为对象(反序列化)非常有用。本包在 Phly\Http\Request\Serializer
和 Phly\Http\Response\Serializer
中提供了这些功能;每个都提供了以下静态方法:
fromString($message)
会从字符串消息创建一个Request
或Response
实例(根据使用的序列化器而定)。fromStream(Psr\Http\Message\StreamInterface $stream)
会从提供的流创建一个Request
或Response
实例(根据使用的序列化器而定)。toString(Psr\Http\Message\RequestInterface|Psr\Http\Message\ResponseInterface $message)
会从提供的消息创建一个字符串。
反序列化方法(from*()
)在解析消息时如果发生错误会抛出异常。序列化方法(toString()
)如果消息实例中不存在序列化所需的数据也会抛出异常。