PHP规范PSR7(HTTP消息接口)介绍(二)

1.3 流

HTTP消息由起始行,标题和正文组成。 HTTP消息的主体可能非常小或非常大。尝试将消息正文表示为字符串很容易消耗比预期更多的内存,因为正文必须完全存储在内存中。尝试将请求或响应的主体存储在内存中将阻止使用该实现能够使用大型消息体。 StreamInterface用于在读取或写入数据流时隐藏实现细节。对于字符串是适当的消息实现的情况,可以使用内置流,例如php:// memory和php:// temp。

StreamInterface公开了几种方法,可以有效地读取,写入和遍历流。

Streams使用三种方法公开它们的功能:isReadable(),isWritable()和isSeekable()。流协作者可以使用这些方法来确定流是否能够满足其要求。

每个流实例都具有各种功能:它可以是只读,只写或读写。它还可以允许任意随机访问(向前或向后搜索任何位置),或仅允许顺序访问(例如,在套接字,管道或基于回调的流的情况下)。

最后,StreamInterface定义了一个__toString()方法,以简化一次检索或发出整个主体内容的过程。

与请求和响应接口不同,StreamInterface不会对不可变性进行建模。在包装实际PHP流的情况下,不可能实现不可变性,因为与资源交互的任何代码都可能潜在地改变其状态(包括光标位置,内容等)。我们的建议是实现使用只读流来处理服务器端请求和客户端响应。消费者应该意识到流实例可能是可变的,因此可能会改变消息的状态;如有疑问,请创建一个新的流实例并将其附加到消息以强制执行状态。

1.4 请求目标和URI

根据RFC 7230,请求消息包含“请求目标”作为请求行的第二个段。请求目标可以是以下形式之一:

origin-form,由路径和查询字符串(如果存在)组成;这通常被称为相对URL。通过TCP传输的消息通常是原始形式;方案和权限数据通常仅通过CGI变量存在。

absolute-form,由方案,权限(“[user-info @] host [:port]”,括号中的项是可选的),路径(如果存在),查询字符串(如果存在)和片段(如果存在)。这通常被称为绝对URI,并且是RFC 3986中详细说明的唯一指定URI的形式。此表单通常在向HTTP代理发出请求时使用。

authority-form,仅由权威机构组成。这通常仅用于CONNECT请求,以在HTTP客户端和代理服务器之间建立连接。

asterisk-form,仅由字符串*组成,与OPTIONS方法一起使用,以确定Web服务器的常规功能。

除了这些请求目标之外,通常还有一个与请求目标分开的“有效URL”。有效URL不在HTTP消息中传输,但它用于确定用于发出请求的协议(http / https),端口和主机名。

有效的URL由UriInterface表示。 UriInterface模拟RFC 3986(主要用例)中指定的HTTP和HTTPS URI。该接口提供了与各种URI部分交互的方法,这将消除重复解析URI的需要。它还指定了一个__toString()方法,用于将建模的URI转换为其字符串表示形式。

使用getRequestTarget()检索请求目标时,默认情况下,此方法将使用URI对象并提取所有必需的组件来构造原始表单。原始形式是迄今为止最常见的请求目标。

如果最终用户希望使用其他三种表单中的一种,或者如果用户想要显式覆盖请求目标,则可以使用withRequestTarget()来执行此操作。

调用此方法不会影响URI,因为它是从getUri()返回的。

例如,用户可能希望向服务器发出星号形式的请求:

$request = $request
    ->withMethod('OPTIONS')
    ->withRequestTarget('*')
    ->withUri(new Uri('https://example.org/'));

此示例最终可能会导致HTTP请求如下所示:

OPTIONS * HTTP/1.1

但HTTP客户端将能够使用有效的URL(来自getUri())来确定协议,主机名和TCP端口。

HTTP客户端必须忽略Uri :: getPath()和Uri :: getQuery()的值,而是使用getRequestTarget()返回的值,默认为连接这两个值。

选择不实现4个请求目标表单中的一个或多个的客户端必须仍然使用getRequestTarget()。这些客户端必须拒绝它们不支持的请求目标,并且不得依赖于getUri()的值。

RequestInterface提供了检索请求目标或使用提供的请求目标创建新实例的方法。默认情况下,如果实例中没有专门组合请求目标,则getRequestTarget()将返回组合URI的原始形式(如果没有组成URI,则返回“/”)。 withRequestTarget($ requestTarget)使用指定的请求目标创建一个新实例,从而允许开发人员创建表示其他三个请求目标表单(绝对表单,权限表单和星号表单)的请求消息。使用时,组合的URI实例仍然可以使用,特别是在客户端中,它可以用于创建与服务器的连接。

猜你喜欢

转载自blog.csdn.net/u013702678/article/details/83479597