diff --git a/accepted/PSR-17-http-factory-meta.md b/accepted/PSR-17-http-factory-meta.md index 97679e1f8..d952b9a17 100644 --- a/accepted/PSR-17-http-factory-meta.md +++ b/accepted/PSR-17-http-factory-meta.md @@ -268,6 +268,41 @@ the time this proposal was developed allowed a string URI when creating a `UriInterface` implementation they provided. As such, accepting a string is expedient and follows existing semantics. +### 5.7 Why are Streams created with the specified read/write pointer positions? + +The `StreamFactoryInterface::createStreamFromFile()` method implementation +typically maps directly to an `fopen()` call and, in terms of the read/write +pointer position, should behave consistently with `fopen()` with regards to +the `$mode` argument, as covered by the +[PHP manual page](http://php.net/manual/en/function.fopen.php). + +The primary use case for `StreamFactoryInterface::createStream()` is to +create streams for the body of a `ResponseInterface` instance to be emitted +as an HTTP response. It can also be used to create an empty stream, which +can subsequently be written to. + +An emitter can make no assumptions about streams (or their internal resource +handles) being repeatable, and therefore can't simply `rewind()` the stream. + +Even in the case where a stream returns `true` for `isSeekable()`, rewinding +the stream could have unacceptable performance implications. Similarly, the +`__toString()` method results in unacceptable memory overhead for large streams. + +Consequently, to efficiently emit the body stream of a `ResponseInterface` +instance as body of an HTTP response, we must be able to make an assumption +about the stream pointer being positioned at the beginning of the stream. + +As for `StreamFactoryInterface::createStreamFromResource()`, the caller is +responsible for the creation of the PHP resource to use as the basis for the +stream, and therefore also assumes responsibility for the read/write pointer +state of the resource and resulting stream. + +And finally, the instances created by the `RequestFactoryInterface`, +`ResponseFactoryInterface` and `ServerRequestFactoryInterface` factories +must generate instances that return an empty `StreamInterface` instance in +read and write mode, so that client-code can start writing to the body stream, +without manually needing to initialize anything else. + ## 6. People This PSR was produced by a FIG Working Group with the following members: @@ -306,3 +341,23 @@ _**Note:** Order descending chronologically._ - [shadowhand Dependency Inversion and PSR-7 Bodies](http://shadowhand.me/dependency-inversion-and-psr-7-bodies/) - [PHP-FIG mailing list thread discussing factories](https://groups.google.com/d/msg/php-fig/G5pgQfQ9fpA/UWeM1gm1CwAJ) - [PHP-FIG mailing list thread feedback on proposal](https://groups.google.com/d/msg/php-fig/piRtB2Z-AZs/8UIwY1RtDgAJ) + +## 9. Errata + +This recommendation initially omitted the following requirements. + +### 9.1 `StreamFactoryInterface::createStream()` + +The state of the created temporary resource was unspecified - per section 5.7, the +requirement was added to position the temporary resource at the beginning of the stream. + +### 9.2 `StreamFactoryInterface::createStreamFromFile()` + +The state of the created temporary resource was unspecified - per section 5.7, the +requirement was added to position the resource consistently with `fopen()`. + +### 9.3 `StreamFactoryInterface::createStreamFromResource()` + +The requirements did not specify whether this method might affect the state of the given +resource - per section 5.7, the requirement was added to clarify that this method MUST NOT +modify the position of the given resource. diff --git a/accepted/PSR-17-http-factory.md b/accepted/PSR-17-http-factory.md index cf7b31c88..cb1e00286 100644 --- a/accepted/PSR-17-http-factory.md +++ b/accepted/PSR-17-http-factory.md @@ -51,6 +51,8 @@ interface RequestFactoryInterface } ``` +The created instance MUST return an empty `StreamInterface` instance in read and write mode. + ### 2.2 ResponseFactoryInterface Has the ability to create responses. @@ -74,6 +76,8 @@ interface ResponseFactoryInterface } ``` +The created instance MUST return an empty `StreamInterface` instance in read and write mode. + ### 2.3 ServerRequestFactoryInterface Has the ability to create server requests. @@ -102,6 +106,8 @@ interface ServerRequestFactoryInterface } ``` +The created instance MUST return an empty `StreamInterface` instance in read and write mode. + ### 2.4 StreamFactoryInterface Has the ability to create streams for requests and responses. @@ -117,6 +123,9 @@ interface StreamFactoryInterface * Create a new stream from a string. * * The stream SHOULD be created with a temporary resource. + * + * The stream MUST be created with the current position of the file read/write + * pointer at the beginning of the stream. (Errata 9.1) * * @param string $content String content with which to populate the stream. */ @@ -130,6 +139,10 @@ interface StreamFactoryInterface * * The `$filename` MAY be any string supported by `fopen()`. * + * The stream MUST be created with the current position of the file read/write + * pointer positioned consistently with that of `fopen()` with regards to + * the `$mode` flag. (Errata 9.2) + * * @param string $filename The filename or stream URI to use as basis of stream. * @param string $mode The mode with which to open the underlying filename/stream. * @@ -143,6 +156,8 @@ interface StreamFactoryInterface * * The stream MUST be readable and may be writable. * + * The current read/write position of the given PHP resource MUST NOT be modified. (Errata 9.3) + * * @param resource $resource The PHP resource to use as the basis for the stream. */ public function createStreamFromResource($resource): StreamInterface;