ServerResponse interface for PSR-7

238 views
Skip to first unread message

Dracony

unread,
Mar 26, 2015, 7:11:07 PM3/26/15
to php...@googlegroups.com
I have just read through the PSR7 again and this time it dawned on me. I now know how to fix all that was bothering me.

This PSR needs a ServerResponse interface as a counterpart to ServerRequest. ServerRequest provides access to cookies via a separate methid and it seems logical for a ServerResponse to exists that also provides the ability to modify cookies.

Marco Pivetta

unread,
Mar 26, 2015, 7:21:17 PM3/26/15
to php...@googlegroups.com
On 26 March 2015 at 23:11, Dracony <draco...@gmail.com> wrote:
I have just read through the PSR7 again and this time it dawned on me. I now know how to fix all that was bothering me.

This PSR needs a ServerResponse interface as a counterpart to ServerRequest. ServerRequest provides access to cookies via a separate methid and it seems logical for a ServerResponse to exists that also provides the ability to modify cookies.

I still don't understand what the big deal with cookies is. A cookie is just a header, and headers are already in the interface.

Marco Pivetta

http://twitter.com/Ocramius     

http://ocramius.github.com/

Roman Tsjupa

unread,
Mar 26, 2015, 7:40:32 PM3/26/15
to php...@googlegroups.com
The problem is with having to parse them into headers manually. The rest of the PSR is possible to implement using ready made functions like header(), IncomingServerRequest::getCookieParams actually requires you to be compatible with $_COOKIE, but the process of actually setting the cookies will not be achievable without of the developer having to implement cookie to header encoding himself. I believe that it's very important for this PSR to be trivial to implement with the available php function library, and it's only the cookies that stand in its way.

Actually I think the implementation that wraps around header(), setcookie() and string Messages should be the "default" implementation since then all improvements to PHP  handling these things will automatically be picked up

--
You received this message because you are subscribed to a topic in the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/php-fig/6zesbZWLY_Y/unsubscribe.
To unsubscribe from this group and all its topics, 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/CADyq6sLcnf%3DUMCqAPpoePWSmH3%2BhGd2QeCNEZZqJCTXEDqs6ng%40mail.gmail.com.

For more options, visit https://groups.google.com/d/optout.

Marco Pivetta

unread,
Mar 26, 2015, 7:42:19 PM3/26/15
to php...@googlegroups.com
On 26 March 2015 at 23:40, Roman Tsjupa <draco...@gmail.com> wrote:
The problem is with having to parse them into headers manually.

This is exactly what I'm wondering about: why is it a problem?

Roman Tsjupa

unread,
Mar 26, 2015, 7:49:38 PM3/26/15
to php...@googlegroups.com
There's a lot to account for when implementing that:

We already have a good tool for setting cookies, that comes bundled with PHP in the standard library and is used by pretty much every app out there. Forcing everyone to switch from that working tool ( setcoockie() ) is kind of suboptimal

--
You received this message because you are subscribed to a topic in the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/php-fig/6zesbZWLY_Y/unsubscribe.
To unsubscribe from this group and all its topics, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

Marco Pivetta

unread,
Mar 26, 2015, 7:55:11 PM3/26/15
to php...@googlegroups.com
On 26 March 2015 at 23:49, Roman Tsjupa <draco...@gmail.com> wrote:
There's a lot to account for when implementing that:

We already have a good tool for setting cookies, that comes bundled with PHP in the standard library and is used by pretty much every app out there. Forcing everyone to switch from that working tool ( setcoockie() ) is kind of suboptimal

It seems to me that you are confusing again what this PSR is about.

The PSR is about "representing" a message, not about pushing it back and forth.

Any generic PSR-7 compliant "send_cookies(Response $message) {...}" will just work fine with *this representation* of the http messages.

Don't confuse transmitting the message with representing a message: those are two very different concerns.

Writing a single good "cookie sender" implementation isn't that hard, and we honestly just need a couple:

 - one that uses the internal PHP web SAPI (which actually works, but meh)
 - one that allows usage with tools like ReactPHP, where PHP is also dealing with lower level request/response and transport operations

There is no need for an overhaul of the "representation" of a message if the serialization can be obtained from it anyway, and especially if it's only for an edge case.

Roman Tsjupa

unread,
Mar 26, 2015, 8:09:22 PM3/26/15
to php...@googlegroups.com
Ok, I'm clearly not getting my point through, let me try to describe what I mean step by step.

Important part: at no point do I suggest that any implementation of this PSR should have anything to do with setcookie(), I mean something different.

You are right that the Response interface should only concern itself with representing, not printing. My original point was that since the response doesn't provide a getCookies(), getCookie(), setCookie() methods, the only way to add a cookie to a Response is this:

->withAddedHeader('Set-Cookie', '<Cookie data parsed into header>')

So as it is right now the PSR forces you to encode cookies into headers yourself.


Now imagine a setCookie(), getCookie() etc. methods were added to the Response interface. This way cookie data would be represented as an array of CookieInterface instances. This way when printing out the response we would be able to do this:

foreach($response->getCookies() as $cookie) {
    setcooke($cookie->getName()...);
}


So what I'm saying is that representing Cookies as parameters ( or CookieInterface instances ) is a much more flexible way that also enables us to use a native setcookie() function for writing the headers.

With the current PSR7 Response interface this is not possible, since it requires you to treat cookies as any other header and set them in the parsed version.

--
You received this message because you are subscribed to a topic in the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/php-fig/6zesbZWLY_Y/unsubscribe.
To unsubscribe from this group and all its topics, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

Paul M. Jones

unread,
Mar 26, 2015, 8:15:50 PM3/26/15
to php...@googlegroups.com

> On Mar 26, 2015, at 19:09, Roman Tsjupa <draco...@gmail.com> wrote:
>
> So as it is right now the PSR forces you to encode cookies into headers yourself.

Correct, and this was intentional.

I originally thought as you did, that cookies were a special case (and reasonably so, with lots of evidence to back that case).

However, MWOP (among others?) pointed out that a helper function/class/whatever can correctly format a Cookie header for insertion into the Message. As a follow-on, helper functions/classes can correctly format other kinds of specific-use headers (Cache, etc).

As such, cookies get treated like any other header, their "specialness" as defined by authoritative sources notwithstanding.



--
Paul M. Jones
pmjo...@gmail.com
http://paul-m-jones.com

Modernizing Legacy Applications in PHP
https://leanpub.com/mlaphp

Solving the N+1 Problem in PHP
https://leanpub.com/sn1php


Marco Pivetta

unread,
Mar 26, 2015, 8:16:19 PM3/26/15
to php...@googlegroups.com
On 27 March 2015 at 00:09, Roman Tsjupa <draco...@gmail.com> wrote:
Ok, I'm clearly not getting my point through, let me try to describe what I mean step by step.

Important part: at no point do I suggest that any implementation of this PSR should have anything to do with setcookie(), I mean something different.

You are right that the Response interface should only concern itself with representing, not printing. My original point was that since the response doesn't provide a getCookies(), getCookie(), setCookie() methods, the only way to add a cookie to a Response is this:

->withAddedHeader('Set-Cookie', '<Cookie data parsed into header>')

So as it is right now the PSR forces you to encode cookies into headers yourself.


Now imagine a setCookie(), getCookie() etc. methods were added to the Response interface. This way cookie data would be represented as an array of CookieInterface instances. This way when printing out the response we would be able to do this:

foreach($response->getCookies() as $cookie) {
    setcooke($cookie->getName()...);
}


So what I'm saying is that representing Cookies as parameters ( or CookieInterface instances ) is a much more flexible way that also enables us to use a native setcookie() function for writing the headers.

With the current PSR7 Response interface this is not possible, since it requires you to treat cookies as any other header and set them in the parsed version.

So you are basically suggesting a better representation for some particular headers.

Let me re-state what I said above: a cookie is *just a header*.
Yes, its contents may be formatted differently, but it's still just a header, and it still fits the representation of a header.

If you go down this "specific case scenario" way, you start having separate VOs for each kind of header (which is what some libraries do), and that' is already way too specific.

There's no real benefit in that: just create a header parser if you need to do that.

Roman Tsjupa

unread,
Mar 26, 2015, 8:37:57 PM3/26/15
to php...@googlegroups.com
However, MWOP (among others?) pointed out that a helper function/class/whatever can correctly format a Cookie header for insertion into the Message. As a follow-on, helper functions/classes can correctly format other kinds of specific-use headers (Cache, etc).
That would mean that  wherever you pass a Request instance you'd have to pass the CookieFormatter alongside it, without it the functionality won't be complete, and in fact we need a CookieFormatterInterface included int the PSR in that case. Here is why:

Imagine you are developing a "middleware" framework agnostic authentication library, you make it rely on the PSR7 so that you can truly be independent of the framework. User enters a correct password or whatever and you decide to set him a cookie saying that he is now logged in. How do you do that? Suddenly your library that does something else entirely ( matches passwords) has to be able to encode a cookie into a header. What options does it have? It has to either rely on the frameworks CookieFromatter, but then it;s not really framework agnostic, or it can depends on some CookieFromatter package, which is ok, but as I said before that CookieFormatter will just endup being dragged all over the place with Response instances.

If you go down this "specific case scenario" way, you start having separate VOs for each kind of header (which is what some libraries do), and that' is already way too specific.
I think it's enough to provide specific VOs only for things that PHP has support in its standard library for ( like headers and cookies). As Phil once told me: "don't you slippery slope me" =)


At any rate even if it's not the "pure" way, I believe it is the most useful one. Especially since it will eliminate the need of the CookieFormatter entirely, we really really don't need that. 

Thats why as a compromise I propose the addition of a ServerResponse. This one would have cookies as VOs, while the actual Response would be "pure". Especially since PSR7 already strides away from "pureness" with support for $_FILES.

--
You received this message because you are subscribed to a topic in the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/php-fig/6zesbZWLY_Y/unsubscribe.
To unsubscribe from this group and all its topics, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

Marco Pivetta

unread,
Mar 26, 2015, 8:44:20 PM3/26/15
to php...@googlegroups.com
 > for things that PHP has support in its standard library for ( like headers and cookies).

For something that 2% of the apps out there do? Seriously, what do you *still* do with cookies nowadays? Isn't the default session stuff enough.

If we start introducing this way of thinking, I'd say that content negotiation and cache control are much much *much* *MUCH* more relevant ;-)

Just keep them all as "headers", no exceptions, and you'll be fine.

--
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.

Roman Tsjupa

unread,
Mar 26, 2015, 8:51:41 PM3/26/15
to php...@googlegroups.com
Cookies and sessions have somewhat different applications. Storing non-sensitive data in sessions for highload websites is a waste of both space and I/O. There's no need to start a session for a user who just wants to change the language on the site. PHP doesn't have native support for content negotiation nor cache control, so I really don't follow that line of thought.

Also, speaking of sessions, does the session cookie have to be represented when you call getHeaders() ? It is set by PHP itself.

Marco Pivetta

unread,
Mar 26, 2015, 9:00:38 PM3/26/15
to php...@googlegroups.com
On 27 March 2015 at 00:51, Roman Tsjupa <draco...@gmail.com> wrote:
There's no need to start a session for a user who just wants to change the language on the site.

Just start a session, really: don't over-complicate it for the sake of it.
 
PHP doesn't have native support for content negotiation nor cache control, so I really don't follow that line of thought.

Hello? Is this 2015? Are we building APIs or is this Yahoo Geocities? I realize that this may sound harsh, but I didn't explicitly use `setcookie()` since years, and instead we're dealing with "Accept", "Content-Type" and JSON response/request bodies. Web browsers are only a little part of the user-agents that this specification is trying to target.

Also, speaking of sessions, does the session cookie have to be represented when you call getHeaders() ? It is set by PHP itself.

Yes, it is done via cookies by ext/session, and no, you don't need to deal with it manually, therefore you don't need to deal with it even with a manually crafted response sender (assuming WEB SAPI and standard mod_php/cgi/fastcgi + webserver), because the cookies for sessions are going out anyway.

Roman Tsjupa

unread,
Mar 26, 2015, 9:14:17 PM3/26/15
to php...@googlegroups.com
So how exactly will Accept and Content-Type help you if a user decides he wants to read your article in German? some articles allow you to adjust font size, lets fire up a session for that too? Cookies are widely used for tracking too. Invoking geocities is really irrelevant.

--
You received this message because you are subscribed to a topic in the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/php-fig/6zesbZWLY_Y/unsubscribe.
To unsubscribe from this group and all its topics, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

Marco Pivetta

unread,
Mar 26, 2015, 9:31:19 PM3/26/15
to php...@googlegroups.com
On 27 March 2015 at 01:14, Roman Tsjupa <draco...@gmail.com> wrote:
So how exactly will Accept and Content-Type help you if a user decides he wants to read your article in German? 
some articles allow you to adjust font size, lets fire up a session for that too? Cookies are widely used for tracking too. Invoking geocities is really irrelevant.

Invoking geocities is relevant mainly because I'm trying to show you that your arguments are based on practices that *were* relevant in an age where having a visitors counter was "hip".

 - tracking can be done *without* cookies at all ( http://en.wikipedia.org/wiki/Evercookie )
 - just start a session for user preferences, for all the rest there's content negotiation (yep, language choice is part of it)
 - Accept and Content-Type are concepts that became relevant when the PHP world realized that we were missing JAX-RS, and now we're getting there
 - add more stuff here...

What I'm saying is that you're still beating a dead horse: a cookie is just a header like any other, and then its internal formatting is just a detail.
The fact that PHP has an implementation for dealing with cookies (which, by the way, works only with the web SAPI - how many times do I have to say that?) does not make cookies a "privileged" aspect of HTTP, and that simply means that there shouldn't be a privileged API on the HTTP message representation.

Besides that, dealing with cookies directly causes more security issues than solutions.

Roman Tsjupa

unread,
Mar 26, 2015, 9:43:19 PM3/26/15
to php...@googlegroups.com
 for all the rest there's content negotiation (yep, language choice is part of it)
Selecting a different language from a dropdown on a  site won't affect your browsers Accept headers

 tracking can be done *without* cookies at all ( http://en.wikipedia.org/wiki/Evercookie )
And if we actually represented Cookies as parameters a developer with then implement a CookieWriter in such a way that it turns all set cookies into those Evercookies. You actually strengthened my idea about Cookie abstraction with this. 

Besides that, dealing with cookies directly causes more security issues than solutions.
The number 1 rule is not to use them for sensitive stuff

But why would you be so opposed to a separate ServerResponse interface? It still would be trivially transformable into actual Response.And Serverrequest already does have exceptions for cookie and upload handling. Doesn't it seem logical to you that if we have:

1) Request that knows nothing about cookies
2) Response that knows nothing about cookies
3) ServerRequest that knows about cookies and files

That a ServerResponse that is a counterpart to ServerRequest and does know about cookies is only logical ?

--
You received this message because you are subscribed to a topic in the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/php-fig/6zesbZWLY_Y/unsubscribe.
To unsubscribe from this group and all its topics, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

Beau Simensen

unread,
Mar 27, 2015, 3:53:37 AM3/27/15
to php...@googlegroups.com
On Thursday, March 26, 2015 at 6:11:07 PM UTC-5, Dracony wrote:
I have just read through the PSR7 again and this time it dawned on me. I now know how to fix all that was bothering me.

This PSR needs a ServerResponse interface as a counterpart to ServerRequest. ServerRequest provides access to cookies via a separate methid and it seems logical for a ServerResponse to exists that also provides the ability to modify cookies.

Did you have other reasons to provide a ServerResponse besides dealing with cookies? I've been trying to keep up with this thread but I can't recall seeing what other reasons there might be for needing a ServerResponse other than symmetry.

As has been mentioned by several people now, we decided to not treat any headers as special. Even in the case of cookies it is possible to manage these things without having cookie-specific accessors and mutators on either the request or response interfaces. I started working on a reference implementation of this today to prove out some of the pseudocode I've been writing on the topic of cookies and I'm pretty happy with it so far.

With this API, you do not have to inject a CookieWriter or a CookieReader everywhere, you just ask for it when you need to access a cookie. If you only need one cookie, you can do it all in one line.

    /**
     * @test
     */
    public function it_gets_cookie_value_from_request()
    {
        //
        // Example of accessing a cookie value.
        //

        // Simulate a request coming in with several cookies.
        $request = (new FigCookieTestingRequest())
            ->withHeader(Cookies::COOKIE_HEADER, 'theme=light; sessionToken=RAPELCGRQ; hello=world')
        ;

        $theme = Cookies::fromRequest($request)->get('theme')->getValue();

        $this->assertEquals('light', $theme);
    }

And here is a longer example for a hypothetical middleware that decrypts an incoming cookie so that anyone consuming the request from that point on can request the same cookie and get it in plaintext.

    /**
     * @test
     */
    public function it_gets_and_updates_cookie_value_on_request()
    {
        //
        // Example of naive cookie decryption middleware.
        //
        // Shows how to access and manipulate cookies using PSR-7 Request
        // instances from outside the Request object itself.
        //

        // Simulate a request coming in with several cookies.
        $request = (new FigCookieTestingRequest())
            ->withHeader(Cookies::COOKIE_HEADER, 'theme=light; sessionToken=RAPELCGRQ; hello=world')
        ;

        // Get our cookies from the request.
        $cookies = Cookies::fromRequest($request);

        // Ask for the encrypted session token.
        $encryptedSessionToken = $cookies->get('sessionToken');

        // Get the encrypted value from the cookie and decrypt it.
        $encryptedValue = $encryptedSessionToken->getValue();
        $decryptedValue = str_rot13($encryptedValue);

        // Create a new cookie with the decrypted value.
        $decryptedSessionToken = $encryptedSessionToken->withValue($decryptedValue);

        // Include our decrypted session token with the rest of our cookies.
        $cookies = $cookies->with($decryptedSessionToken);

        // Render our cookies, along with the newly decrypted session token, into a request.
        $request = $cookies->renderIntoCookieHeader($request);

        // From this point on, any request based on this one can get the plaintext version
        // of the session token.
        $this->assertEquals(
            'theme=light; sessionToken=ENCRYPTED; hello=world',
            $request->getHeader(Cookies::COOKIE_HEADER)
        );
    }

I have about half of the SetCookie implementation done but it will be pretty similar. I'll write the outbound part of the hypothetical cookie encryption middleware in those tests.

This API is fresh so I know it isn't perfect. But it isn't horrible, either. It can be optimized and frameworks can provide this type of functionality in helpers that flow better with their style. Said another way, this could be written in any number of ways.

It should also be pointed out that it would be relatively trivial to add a thing cache over this so that repeated queries to parse the same cookie information can just return the previous results.

The big win here is that I just created a framework agnostic way to manage cookies for any potential PSR-7 implementation. Neither PSR-7 nor the lack of setcookie/getcookie on the request/response hindered me at all. This means that if all of the big frameworks create their own cooke management library I can still just use mine if I want to. Or, a framework might opt to just use my implementation because it is one less thing that they'll have to do on their own. Plus, if they ever need to, they can just swap out my cookie implementation for theirs or another of their choosing.

This is all possible because cookies are just a header. We can build whatever tools we want to around managing specific headers and we'll get man smaller but still quite powerful tools.



Dracony

unread,
Mar 27, 2015, 4:06:39 AM3/27/15
to php...@googlegroups.com
With this API, you do not have to inject a CookieWriter or a CookieReader everywhere, you just ask for it when you need to access a cookie. If you only need one cookie, you can do it all in one line.
 
Well I'm really not a fan of your static approach:

$cookies = Cookies::fromRequest($request);

The big win here is that I just created a framework agnostic way to manage cookies for any potential PSR-7 implementation. 
I don't see how having setters/getters for cookies would somehow make it less framework agnostic.

Neither PSR-7 nor the lack of setcookie/getcookie on the request/response hindered me at 
Yes they did because they forced you to do the CookieWriter thingy, which by the way is also not interpolable between frameworks. So now your middleware implementation has a hard dependency on a specific cookie writer.

 Plus, if they ever need to, they can just swap out my cookie implementation for theirs or another of their choosing.
Same would happen if you had cookie getters/setters. How would having cookie params as value object hinder any of the interpolability? 

frameworks can provide this type of functionality in helpers that flow better with their style
But why force frameworks ti provide this functionality if enabling cookie getters and setters will allow the framework to rely on setcookie() if it wants to?  

Marco Pivetta

unread,
Mar 27, 2015, 4:49:42 AM3/27/15
to php...@googlegroups.com
On 27 March 2015 at 08:06, Dracony <draco...@gmail.com> wrote:
With this API, you do not have to inject a CookieWriter or a CookieReader everywhere, you just ask for it when you need to access a cookie. If you only need one cookie, you can do it all in one line.
 
Well I'm really not a fan of your static approach:

$cookies = Cookies::fromRequest($request);

This is just a static constructor/factory: no side-effects, therefore static is OK.
 
The big win here is that I just created a framework agnostic way to manage cookies for any potential PSR-7 implementation. 
I don't see how having setters/getters for cookies would somehow make it less framework agnostic.

It is just bloating up the API: more code to implement for everyone willing to write a PSR-7 implementation, plus cookie-specific mess to deal with, whereas it is a simple key/value map as-is.
 

Neither PSR-7 nor the lack of setcookie/getcookie on the request/response hindered me at 
Yes they did because they forced you to do the CookieWriter thingy, which by the way is also not interpolable between frameworks. So now your middleware implementation has a hard dependency on a specific cookie writer.

So what? A  `CookieWriter` wouldn't have particular side-effects in any case, and the specification is very clear on how to read/write cookies.

 Plus, if they ever need to, they can just swap out my cookie implementation for theirs or another of their choosing.
Same would happen if you had cookie getters/setters. How would having cookie params as value object hinder any of the interpolability? 

Every implementor of PSR-7 would have to code:

 - cookie handling inside the HTTP message logic
 - merging with the headers array

Anyway, I feel like we've looped the discussion more than 3 times now: I'm putting this thread on mute

Lukas Kahwe Smith

unread,
Mar 27, 2015, 4:52:07 AM3/27/15
to php...@googlegroups.com

On 27 Mar 2015, at 09:49, Marco Pivetta <ocra...@gmail.com> wrote:

On 27 March 2015 at 08:06, Dracony <draco...@gmail.com> wrote:
With this API, you do not have to inject a CookieWriter or a CookieReader everywhere, you just ask for it when you need to access a cookie. If you only need one cookie, you can do it all in one line.
 
Well I'm really not a fan of your static approach:

$cookies = Cookies::fromRequest($request);

This is just a static constructor/factory: no side-effects, therefore static is OK.
 
The big win here is that I just created a framework agnostic way to manage cookies for any potential PSR-7 implementation. 
I don't see how having setters/getters for cookies would somehow make it less framework agnostic.

It is just bloating up the API: more code to implement for everyone willing to write a PSR-7 implementation, plus cookie-specific mess to deal with, whereas it is a simple key/value map as-is.

what would be interesting then is to implement a generic lib for any PSR-7 library to add Cookie specific syntax sugar for those who frequently need to work with Cookies.

regards,
Lukas

Dracony

unread,
Mar 27, 2015, 5:00:24 AM3/27/15
to php...@googlegroups.com
It is just bloating up the API: more code to implement for everyone willing to write a PSR-7 implementation, plus cookie-specific mess to deal with, whereas it is a simple key/value map as-is.
Let me implement it for you:

protected $cookies;

public function addCookie(CookieInterface $cookie) {
     $this->cookies[$cookies->getName()] = $cookie;
}

public function getCookie($name) {
     return $this->cookies[$name];
}

There is no cookie specific mess to deal with. It's just an array of stuff

Every implementor of PSR-7 would have to code:
 - cookie handling inside the HTTP message logic
 - merging with the headers array
Well here is where your CookieWriter comes in to parse them into headers. Note that that will happen in one place only, not every miiddleware. Also some devs ( e.g. me) may use setcookie() to write those cookies to the actual client. Everybody wins

Paul M. Jones

unread,
Mar 27, 2015, 8:51:35 AM3/27/15
to php...@googlegroups.com

> On Mar 27, 2015, at 04:00, Dracony <draco...@gmail.com> wrote:
>
> It is just bloating up the API: more code to implement for everyone willing to write a PSR-7 implementation, plus cookie-specific mess to deal with, whereas it is a simple key/value map as-is.
> Let me implement it for you:
>
> protected $cookies;
>
> public function addCookie(CookieInterface $cookie) {
> $this->cookies[$cookies->getName()] = $cookie;
> }
>
> public function getCookie($name) {
> return $this->cookies[$name];
> }
>

That's awesome! Now do it for every header. :-/

Roman Tsjupa

unread,
Mar 27, 2015, 9:22:18 AM3/27/15
to php...@googlegroups.com

Cookies are a very specific case and are much harder to format and parse than other headers. Otherwise we wouldnt have support for them in serverRequest

--
You received this message because you are subscribed to a topic in the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/php-fig/6zesbZWLY_Y/unsubscribe.
To unsubscribe from this group and all its topics, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

Paul M. Jones

unread,
Mar 27, 2015, 10:04:57 AM3/27/15
to php...@googlegroups.com

> On Mar 27, 2015, at 08:22, Roman Tsjupa <draco...@gmail.com> wrote:
>
> Cookies are a very specific case and are much harder to format and parse than other headers.

In fact, they are *so* specific that they don't belong in the PSR.

Roman Tsjupa

unread,
Mar 27, 2015, 10:09:30 AM3/27/15
to php...@googlegroups.com
I totally get the purity argument, honest. All I want is an interface that still allows me to represent data in a way that it is compatible with setcookie(). That is why I suggested ServerResponse for this purpose.

--
You received this message because you are subscribed to a topic in the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/php-fig/6zesbZWLY_Y/unsubscribe.
To unsubscribe from this group and all its topics, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

Paul M. Jones

unread,
Mar 27, 2015, 10:22:38 AM3/27/15
to php...@googlegroups.com

> On Mar 27, 2015, at 09:09, Roman Tsjupa <draco...@gmail.com> wrote:
>
> I totally get the purity argument, honest. All I want is an interface that still allows me to represent data in a way that it is compatible with setcookie(). That is why I suggested ServerResponse for this purpose.

Dude, believe me when I say I get you here. The response (heh) is that with a CookieHelper (or whatever) to build the correct string for you, you won't need setcookie() to send it. You'll only need header().

Roman Tsjupa

unread,
Mar 27, 2015, 10:44:29 AM3/27/15
to php...@googlegroups.com
Ok, guys, I concur. Now that I know that you guys got my point and are still disagreeing with it it's different. Because at first people kept saying that I'd still be able to use setcookie() with the current interface. Saying that, personally I don't consider the result to be very"good" if it is not generic enough to support the most common use case. I don't know of a single framework that doesn't print cookies via setcookie(), even :


Nobody has a CookieWriter, and this PSR froces every framework to now have one, and doesn't even standardize the interface for such a thing. As one of the big concerns for PSRs is the adoption factor I don't believe that forcing a CookieWriter on every framework out there is a good idea, especially since the implementation is not trivial.

So instead of explicitly adding a way to handle cookies this PSR implicitly forces CookieWriters

--
You received this message because you are subscribed to a topic in the Google Groups "PHP Framework Interoperability Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/php-fig/6zesbZWLY_Y/unsubscribe.
To unsubscribe from this group and all its topics, send an email to php-fig+u...@googlegroups.com.
To post to this group, send email to php...@googlegroups.com.

Matthew Weier O'Phinney

unread,
Mar 27, 2015, 1:49:03 PM3/27/15
to php...@googlegroups.com
On Fri, Mar 27, 2015 at 9:44 AM, Roman Tsjupa <draco...@gmail.com> wrote:
> Ok, guys, I concur. Now that I know that you guys got my point and are still
> disagreeing with it it's different. Because at first people kept saying that
> I'd still be able to use setcookie() with the current interface.

This was a mistake on my part. When I've considered usage with Conduit
and the next generation of ZF, the idea will be to use a utility
class/function to create the value for the Set-Cookie header, and add
it to the response. Doing so means that the value does not need to be
treated differently from any other headers at all when emitting the
response.

I consider this a benefit.

When you look at Node, Rack, and WSGI applications, you will see that
this is exactly how they deal with "special" headers as well. A
utility class or function is imported and used to seed the value for
the response object. This is true for a number of headers: cookies,
caching headers, etc. that have complex specifications can be dealt
with in discrete classes or functions and you, as a developer, only
need to know what to pass to them.

This is arguably a better situation than using setcookie(), as
setcookie() has side-effects (emits a header... unless you're in the
console, when it's essentially a no-op), and worse, cannot be
introspected. By aggregating the set-cookie headers, you can test to
see which ones are present, allowing you to unit test or selectively
branch logic based on what cookies were previously specified in the
application.

My guess is that, just like the other ecosystems with HTTP message
abstractions, we'll see a number of libraries pop up around the
various headers that will simplify these interactions. You can already
see it in the PHP community with packages that do things like
decomposing the Accept or Content-Type headers to perform
content-negotiation; most of these accept the header _value_, and then
return something. This is fantastic, as it encourages the single
responsibility principle, and poses generic solutions.

> Saying
> that, personally I don't consider the result to be very"good" if it is not
> generic enough to support the most common use case. I don't know of a single
> framework that doesn't print cookies via setcookie(), even :
>
> symfony2 doesn't do that:
> https://github.com/symfony/HttpFoundation/blob/master/Response.php#L348

This logic becomes different under PSR-7 anyways, as the Response is
not specified as being able to emit itself; you would need to write a
response emitter that pulls information from it and emits it. Yes, the
current implementation may use setcookie — but that doesn't mean
somebody could not be specifying cookies via headers _already_, or
that setcookie() must be used in future. It's an implementation detail
at this point. There are a variety of ways to accomplish the same
thing.
Sessions are another beast entirely due to how PHP handles session
identification and regeneration. That said, the next iteration of
Zend\Session is likely going to be moving away from PHP's internal
session handling, and, as such, would be receiving request and
response instances, meaning cookies will likely be used. Again, just
because something is implemented one way now doesn't mean it's tied to
that implementation forever. Internal implementation details do and
often should change.

> Nobody has a CookieWriter, and this PSR froces every framework to now have
> one, and doesn't even standardize the interface for such a thing. As one of
> the big concerns for PSRs is the adoption factor I don't believe that
> forcing a CookieWriter on every framework out there is a good idea,
> especially since the implementation is not trivial.
>
> So instead of explicitly adding a way to handle cookies this PSR implicitly
> forces CookieWriters

The *message interfaces* are what PSR-7 is specifying. How you get the
data into them is up to the framework and/or end-user developer. Those
are _implementation_ details. The message interfaces are
_interoperability_ details, and are specifying the minimum required
elements for that purpose. Since cookies are headers, the lowest
common denominator is the header. As soon as we start accommodating
special case headers, we step away from the minimum viable interface
and increase implementation complexity.
> 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/CANamvv22AmjNAGiS7y37jGtX63aLAzPVgwd2Z5mOJNkgC%2B%2BJ%2BA%40mail.gmail.com.
>
> For more options, visit https://groups.google.com/d/optout.



--
Matthew Weier O'Phinney
mweiero...@gmail.com
https://mwop.net/

Roman Tsjupa

unread,
Mar 27, 2015, 2:03:43 PM3/27/15
to php...@googlegroups.com

Thanks for your explanation. Though I dont really like it, I'll be implementing this for PHPixie today, for standards sake.

Can you also please answer my other question on immutability, so that I have all the info I need for my implementation ? Thanks

Reply all
Reply to author
Forward
0 new messages