Re: Inviting feedback on my proposed "ASGI" spec

Andrew Godwin <[email protected]> Fri, 11 Mar 2016 09:56:22 -0800
Newsgroups gmane.comp.python.web
Message-ID <CAFwN1urDnMX1JJU_agadxq+mn9LA9fzSbkX_WjVD1veyu8UvAQ@mail.gmail.com>
--===============8195532817836705261==
Content-Type: multipart/alternative; boundary=001a113d1e94452583052dc9a74d

--001a113d1e94452583052dc9a74d
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

On Fri, Mar 11, 2016 at 2:28 AM, Cory Benfield <[email protected]> wrote:

>
> On 10 Mar 2016, at 23:56, Andrew Godwin <[email protected]> wrote:
>
> I would indeed want to require servers to always fold headers together
> into a comma-separated list, as that's what the RFC says, and it then mea=
ns
> applications only have to deal with one kind of multi-header!
>
>
> Wellllll=E2=80=A6.kinda?
>
> The RFC says that multiple headers are *semantically equivalent* to the
> joined form, but does not in any sense require that it be done. (The
> normative language in RFC 7230 is MAY.)
>
> I had this discussion recently with Brian Smith: while there is only one
> correct way to fold/unfold headers, anywhere on the spectrum between
> completely folded and completely unfolded is a perfectly valid
> representation of the HTTP header block. This means that there=E2=80=99s =
no *rules*
> about how a server is supposed to do it, at least from the IETF. ASGI is =
of
> course totally allowed to add its own rules, and requiring that they be
> folded is not terrible.
>
> FWIW, in my experience, I=E2=80=99ve found that =E2=80=9Clist of tuples=
=E2=80=9D is really the
> most likely to be correct way to represent a header block, because it
> provides some assurances to the user that the header block has not been
> aggressively transformed from how it was sent on the wire. While the
> *rules* are that the folded representation is supposed to be semantically
> equivalent to the unfolded representation, there is nonetheless some
> information implicit in those headers being separate.
>
> My intuition when writing this kind of thing is to pass applications (lik=
e
> Django) the most meaningful representation I can, and then allow the
> application to make its own decisions about what meaning they=E2=80=99re =
willing to
> lose. That=E2=80=99s why I=E2=80=99d advocate for =E2=80=9Clist of two-tu=
ples of bytestrings=E2=80=9D as
> the representation. However, I don=E2=80=99t think there=E2=80=99s anythi=
ng *wrong* with
> forcing the headers to be joined by the server where possible: it=E2=80=
=99s just
> not how I=E2=80=99d do it. ;)
>
> Set-cookie is the annoying thing here, though. That's why it's dict
> inbound and list of tuples outbound right now, and I just don't know if I
> want to make the inbound one a list of tuples too, given I do definitely
> want to force servers to concat headers together (unless I find any
> examples of that screwing things up)
>
>
> You could make the inbound one a list of tuples but still require that th=
e
> servers concat headers. The rule then would be that it needs to be possib=
le
> for an application to say `dict(headers)` without any loss of meaning.
>

Yes, I think this is a good argument - my worry has always been that the
"no multiples" is more of a soft rule that some clients might break or some
apps might rely on the ordering/multiplicity of things, so preserving it is
_probably_ helpful (and as you say, it lets the header names go back to
bytestrings).

I'll modify the spec and then update Daphne and Channels to match; I can
leave Channels parsing both types for a bit, at least.

Collin's point about http2's handling of headers is on point, too - if the
new spec is deliberately thinned down to that point but no further, it's
probably wise to follow them since they know much more about it than I do.

Andrew

--001a113d1e94452583052dc9a74d
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><br><div class=3D"gmail_extra"><br><div class=3D"gmail_quo=
te">On Fri, Mar 11, 2016 at 2:28 AM, Cory Benfield <span dir=3D"ltr">&lt;<a=
 href=3D"mailto:[email protected]" target=3D"_blank">[email protected]</a>&=
gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 =
0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style=3D"word-wrap=
:break-word"><br><div><span class=3D""><blockquote type=3D"cite"><div>On 10=
 Mar 2016, at 23:56, Andrew Godwin &lt;<a href=3D"mailto:andrew-g6StKjQqr+wpug/[email protected]=
g" target=3D"_blank">[email protected]</a>&gt; wrote:</div><div><div dir=
=3D"ltr" style=3D"font-family:Helvetica;font-size:12px;font-style:normal;fo=
nt-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;tex=
t-transform:none;white-space:normal;word-spacing:0px"><div class=3D"gmail_e=
xtra"><div class=3D"gmail_quote"><div><br></div><div>I would indeed want to=
 require servers to always fold headers together into a comma-separated lis=
t, as that&#39;s what the RFC says, and it then means applications only hav=
e to deal with one kind of multi-header!</div></div></div></div></div></blo=
ckquote><div><br></div></span><div>Wellllll=E2=80=A6.kinda?</div><div><br><=
/div><div>The RFC says that multiple headers are *semantically equivalent* =
to the joined form, but does not in any sense require that it be done. (The=
 normative language in RFC 7230 is MAY.)</div><div><br></div><div>I had thi=
s discussion recently with Brian Smith: while there is only one correct way=
 to fold/unfold headers, anywhere on the spectrum between completely folded=
 and completely unfolded is a perfectly valid representation of the HTTP he=
ader block. This means that there=E2=80=99s no *rules* about how a server i=
s supposed to do it, at least from the IETF. ASGI is of course totally allo=
wed to add its own rules, and requiring that they be folded is not terrible=
.</div><div><br></div><div>FWIW, in my experience, I=E2=80=99ve found that =
=E2=80=9Clist of tuples=E2=80=9D is really the most likely to be correct wa=
y to represent a header block, because it provides some assurances to the u=
ser that the header block has not been aggressively transformed from how it=
 was sent on the wire. While the *rules* are that the folded representation=
 is supposed to be semantically equivalent to the unfolded representation, =
there is nonetheless some information implicit in those headers being separ=
ate.</div><div><br></div><div>My intuition when writing this kind of thing =
is to pass applications (like Django) the most meaningful representation I =
can, and then allow the application to make its own decisions about what me=
aning they=E2=80=99re willing to lose. That=E2=80=99s why I=E2=80=99d advoc=
ate for =E2=80=9Clist of two-tuples of bytestrings=E2=80=9D as the represen=
tation. However, I don=E2=80=99t think there=E2=80=99s anything *wrong* wit=
h forcing the headers to be joined by the server where possible: it=E2=80=
=99s just not how I=E2=80=99d do it. ;)</div><span class=3D""><br><blockquo=
te type=3D"cite"><div><div dir=3D"ltr" style=3D"font-family:Helvetica;font-=
size:12px;font-style:normal;font-weight:normal;letter-spacing:normal;text-a=
lign:start;text-indent:0px;text-transform:none;white-space:normal;word-spac=
ing:0px"><div class=3D"gmail_extra"><div class=3D"gmail_quote"><div>Set-coo=
kie is the annoying thing here, though. That&#39;s why it&#39;s dict inboun=
d and list of tuples outbound right now, and I just don&#39;t know if I wan=
t to make the inbound one a list of tuples too, given I do definitely want =
to force servers to concat headers together (unless I find any examples of =
that screwing things up)</div></div></div></div></div></blockquote><br></sp=
an></div><div>You could make the inbound one a list of tuples but still req=
uire that the servers concat headers. The rule then would be that it needs =
to be possible for an application to say `dict(headers)` without any loss o=
f meaning.</div></div></blockquote><div><br></div><div>Yes, I think this is=
 a good argument - my worry has always been that the &quot;no multiples&quo=
t; is more of a soft rule that some clients might break or some apps might =
rely on the ordering/multiplicity of things, so preserving it is _probably_=
 helpful (and as you say, it lets the header names go back to bytestrings).=
</div><div><br></div><div>I&#39;ll modify the spec and then update Daphne a=
nd Channels to match; I can leave Channels parsing both types for a bit, at=
 least.</div><div><br></div><div>Collin&#39;s point about http2&#39;s handl=
ing of headers is on point, too - if the new spec is deliberately thinned d=
own to that point but no further, it&#39;s probably wise to follow them sin=
ce they know much more about it than I do.</div><div><br></div><div>Andrew=
=C2=A0</div></div></div></div>

--001a113d1e94452583052dc9a74d--

--===============8195532817836705261==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
Web-SIG mailing list
[email protected]
Web SIG: http://www.python.org/sigs/web-sig
Unsubscribe: https://mail.python.org/mailman/options/web-sig/gcpw-web-sig%40m.gmane.org

--===============8195532817836705261==--