Greetings!
I've spoken with Paul, Phil, and Beau, and they are willing to sponsor if I act as Editor for the proposal.
So, I've said my piece.What I want to hear from YOU is:- What do you think is missing from PSR-7 as it currently stands, and, more importantly, why?
- Have you built anything with the interfaces as they currently stand? What were your experiences?- Have you built anything with middleware before, in any language? If so, what feedback do you have?
>
> I chose to ignore the stream object entirely, because for my purposes I need
> to have access to a stream resource.
> This is my one and only issue with the spec as it stands.
>
> 1. I need to be able to call file_put_contents('php://output',
> $response->getBody()); // or equivalent
This can be done already, without even needing to call file_put_contents():
  $response->setBody(new Stream('php://output'));
That tells the response to use the new stream. When you send it
(usually by calling __toString() or casting to a string), it will
essentially do what you've already described.
> 2. I want to be able to throw streams into stream_select(), or even
> libevent.
You can do this already -- Stream accepts any PHP stream to the
constructor. If you already have the resource handle, you can pass it
around. Alternately, you can do the following:
  $resource = $response->getBody()->detach();
  // pass it to stream_select, etc.
  $response->setBody(new Stream($resource));
If so, I'd propose:
- getQueryArgument($name = null, $default = null)
- getBodyParam($name = null, $default = null)
- getCookie($name = null, $default = null)
- getFile($name = null, $default = null)
- getEnv($name = null, $default = null)
- getServer($name = null, $default = null)
Greetings!
- Have you built anything with the interfaces as they currently stand? What were your experiences?
- Have you built anything with middleware before, in any language? If so, what feedback do you have?
> Except that file_put_contents can accept streams as its second argument. I'm
> dealing with responses from megabytes to multiple gigabytes.
> You'll really don't want to put those in a string.
Oh, silly me -- I missed that both arguments were strings! In this
case, I'd create the stream, do the file_put_contents() operation, and
then pass the new stream into the response:
  $bodyStream = fopen('...', 'rw');
  file_put_contents('php://output', $bodyStream);
  $response->setBody(new Stream($bodyStream));
if your Phly\Http\Server class receives a Response object that it's supposed to return to the client, and it's a multi-gigabyte one, how would it behave? |
>> > 2. I want to be able to throw streams into stream_select(), or even
>> > libevent.
>>
>> You can do this already -- Stream accepts any PHP stream to the
>> constructor. If you already have the resource handle, you can pass it
>> around. Alternately, you can do the following:
>>
>> Â Â $resource = $response->getBody()->detach();
>> Â Â // pass it to stream_select, etc.
>> Â Â $response->setBody(new Stream($resource));
>
>
> In the current draft 'detach' does not have a return value. If it did, and
> it always returned a PHP stream then I have no problem at all and 100% on
> board with the draft as-is.
Michael had made it clear in his blog post making a case for streams
that this was the intention, which is why I implemented it that way in
phly/http. I'll update the proposal to reflect this!
Yes, of course I saw these. :) Although, to be fair, you're onlyÂ
really doing the stream interface, correct? The GuzzleÂ
request/response interfaces look quite different from PSR-7 (thoughÂ
their underlying MessageInterface is basically identical). Or am IÂ
missing something?Â
I considered trying to use these briefly, but they are definitelyÂ
geared more toward the client, and ease of creating requests andÂ
parsing responses, from what I could see. PSR-7 feels like a layerÂ
that would lie underneath that.Â
 I'd argue that an interface _is_ a specification. The difference isÂ
one of _type_, with an interface being a specification for objects.Â
Objects are of interest for this particular specification as they canÂ
allow for behaviors you cannot get with arrays:Â
- I can decorate an object in order to change behavior. As an example,Â
I can make a Request or Response immutable via decoration.Â
- I can filter what is returned from an object through extension orÂ
decoration; the same is not true of an array.Â
- I can add behavior via decoration or extension (as an example, inÂ
Conduit, I made it possible to add arbitrary properties to the RequestÂ
object by decorating it; I added a "write" method to the Response thatÂ
proxies to the underlying stream, also via decoration).Â
While I think the Ring specification is well done, I think forÂ
purposes of interop, interfaces will cause less confusion and lessÂ
interoperability issues. Â
--
You received this message because you are subscribed to the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/php-fig/57262e45-93bc-4b71-83e9-fcd9677b507c%40googlegroups.com.
On Sep 27, 2014 2:14 AM, "Chris Wilkinson" <chriswil...@gmail.com> wrote:
> So, this is what the proposal should try and solve, and that’s it. This means two interfaces (request and response), with getters for all the parts of the message, and nothing more. The body should a string or something that can be cast to a string; headers treated as a set of key - string value pairs.
>
> There should not be a MessageInterface (there’s really no need for it), and there should not be a body, stream or whatever interface.
The MessageInterface exists to abstract out the aspects common to both requests and responses (in fact, the http specification itself does this! See http://tools.ietf.org/html/rfc2616 ). You will rarely, if ever, typehint on that interface; you'll instead typehint on the more specific request or response interfaces, which _extend_ it. But it needs to be there.
While I understand some of the arguments against an interface for the body type, I personally feel they are short-sighted. For http clients, this becomes a memory issue: sending or receiving large files within a php process is very common for these purposes, and something that just casts to a string will quickly reach memory limits... When representation as a stream will solve the problem. On the server side, eventually somebody wants to return a file - and, again, if your body is only representable as a string, you hit memory limits when you cast to a string, leading to a need to have separate response does for files and separate APIs for dealing with responses that will return files. Similarly, using a string for a request can lead to issues when dealing with file uploads.
Using a stream-based body for http messages as the default since these issues. You can cast to a string if desired, **or** treat it as a stream - but it's the same API every time.
Most hesitation I've seen about using streams is, in my opinion, due to unfamiliarity with streams and/or worries that implementations will be difficult to write. My answer to that question is: please look at my reference implementation (https://github.com/phly/http) and am example of using it (http://github.com/phly/conduit). Requests can directly wrap php://input - a stream - and the simplest way to do a response wraps a php://memory stream. As a consumer, these are implementation details you largely ignore... Until you need to send a file or want to pass the request body to XMLReader, at which point you can do so without any extra overhead or code acrobatics.
It's for these same reasons that node models the message bodies as streams as well. The paradigm enables any use case, from simple to advanced.
I stand firmly by streams as the basis for the message bodies.