Re: Inviting feedback on my proposed "ASGI" spec

Collin Anderson <[email protected]> Fri, 11 Mar 2016 13:03:35 -0500
Newsgroups gmane.comp.python.web
Message-ID <CAFO84S4WhX_iJTFiAw+vVMbaZyn95jNEcUfRMkSX3G1aCSKWUw@mail.gmail.com>
--===============7350659520008711350==
Content-Type: multipart/alternative; boundary=089e011604261e4e6f052dc9c1f3

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

http2 makes all header names lowercase

On Fri, Mar 11, 2016 at 12:59 PM, Andrew Godwin <[email protected]> wrote=
:

> One thing I did want to ask - is it worth still squashing everything down
> to the same case? Daphne already clears out headers with _ in them to avo=
id
> that CVE about it, and header case is never semantic, or so I thought?
>
> Andrew
>
> On Fri, Mar 11, 2016 at 9:56 AM, Andrew Godwin <[email protected]>
> wrote:
>
>>
>>
>> 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 m=
eans
>>> 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 on=
e
>>> 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=99=
s no *rules*
>>> about how a server is supposed to do it, at least from the IETF. ASGI i=
s 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 semantical=
ly
>>> 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
>>> (like Django) the most meaningful representation I can, and then allow =
the
>>> application to make its own decisions about what meaning they=E2=80=99r=
e willing to
>>> lose. That=E2=80=99s why I=E2=80=99d advocate for =E2=80=9Clist of two-=
tuples of bytestrings=E2=80=9D as
>>> the representation. However, I don=E2=80=99t think there=E2=80=99s anyt=
hing *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 definitel=
y
>>> 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
>>> 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 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 s=
ome
>> 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 tha=
n I
>> do.
>>
>> Andrew
>>
>
>
> _______________________________________________
> Web-SIG mailing list
> [email protected]
> Web SIG: http://www.python.org/sigs/web-sig
> Unsubscribe:
> https://mail.python.org/mailman/options/web-sig/cmawebsite%40gmail.com
>
>

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

<div dir=3D"ltr">http2 makes all header names lowercase</div><div class=3D"=
gmail_extra"><br><div class=3D"gmail_quote">On Fri, Mar 11, 2016 at 12:59 P=
M, Andrew Godwin <span dir=3D"ltr">&lt;<a href=3D"mailto:andrew-g6StKjQqr+wpug/[email protected]=
g" target=3D"_blank">[email protected]</a>&gt;</span> wrote:<br><blockquo=
te class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc so=
lid;padding-left:1ex"><div dir=3D"ltr">One thing I did want to ask - is it =
worth still squashing everything down to the same case? Daphne already clea=
rs out headers with _ in them to avoid that CVE about it, and header case i=
s never semantic, or so I thought?<span class=3D"HOEnZb"><font color=3D"#88=
8888"><div><br></div><div>Andrew</div></font></span></div><div class=3D"HOE=
nZb"><div class=3D"h5"><div class=3D"gmail_extra"><br><div class=3D"gmail_q=
uote">On Fri, Mar 11, 2016 at 9:56 AM, Andrew Godwin <span dir=3D"ltr">&lt;=
<a href=3D"mailto:[email protected]" target=3D"_blank">andrew-g6StKjQqr+wpug/[email protected]=
g</a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margi=
n:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir=3D"ltr">=
<br><div class=3D"gmail_extra"><br><div class=3D"gmail_quote"><span>On Fri,=
 Mar 11, 2016 at 2:28 AM, Cory Benfield <span dir=3D"ltr">&lt;<a href=3D"ma=
ilto:[email protected]" target=3D"_blank">[email protected]</a>&gt;</span> =
wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;bord=
er-left:1px #ccc solid;padding-left:1ex"><div style=3D"word-wrap:break-word=
"><br><div><span><blockquote type=3D"cite"><div>On 10 Mar 2016, at 23:56, A=
ndrew Godwin &lt;<a href=3D"mailto:[email protected]" target=3D"_blank">a=
[email protected]</a>&gt; wrote:</div><div><div dir=3D"ltr" style=3D"font-=
family:Helvetica;font-size:12px;font-style:normal;font-weight:normal;letter=
-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-=
space:normal;word-spacing:0px"><div class=3D"gmail_extra"><div class=3D"gma=
il_quote"><div><br></div><div>I would indeed want to require servers to alw=
ays fold headers together into a comma-separated list, as that&#39;s what t=
he RFC says, and it then means applications only have to deal with one kind=
 of multi-header!</div></div></div></div></div></blockquote><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 this discussion recently w=
ith Brian Smith: while there is only one correct way to fold/unfold headers=
, anywhere on the spectrum between completely folded and completely unfolde=
d 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 rule=
s, 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 way to represent a header=
 block, because it provides some assurances to the user that the header blo=
ck 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 sema=
ntically equivalent to the unfolded representation, there is nonetheless so=
me information implicit in those headers being separate.</div><div><br></di=
v><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 meaning they=E2=80=99re w=
illing to lose. That=E2=80=99s why I=E2=80=99d advocate for =E2=80=9Clist o=
f two-tuples of bytestrings=E2=80=9D as the representation. However, I don=
=E2=80=99t think there=E2=80=99s anything *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. ;)</div><span><br><blockquote 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-align:start;text-indent:0px;text-t=
ransform:none;white-space:normal;word-spacing:0px"><div class=3D"gmail_extr=
a"><div class=3D"gmail_quote"><div>Set-cookie is the annoying thing here, t=
hough. That&#39;s why it&#39;s dict inbound and list of tuples outbound rig=
ht now, and I just don&#39;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 header=
s together (unless I find any examples of that screwing things up)</div></d=
iv></div></div></div></blockquote><br></span></div><div>You could make the =
inbound one a list of tuples but still require that the servers concat head=
ers. The rule then would be that it needs to be possible for an application=
 to say `dict(headers)` without any loss of meaning.</div></div></blockquot=
e><div><br></div></span><div>Yes, I think this is a good argument - my worr=
y has always been that the &quot;no multiples&quot; is more of a soft rule =
that some clients might break or some apps might rely on the ordering/multi=
plicity 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 and Channels to match; I ca=
n leave Channels parsing both types for a bit, at least.</div><div><br></di=
v><div>Collin&#39;s point about http2&#39;s handling of headers is on point=
, too - if the new spec is deliberately thinned down to that point but no f=
urther, it&#39;s probably wise to follow them since they know much more abo=
ut it than I do.</div><span><font color=3D"#888888"><div><br></div><div>And=
rew=C2=A0</div></font></span></div></div></div>
</blockquote></div><br></div>
</div></div><br>_______________________________________________<br>
Web-SIG mailing list<br>
<a href=3D"mailto:[email protected]">[email protected]</a><br>
Web SIG: <a href=3D"http://www.python.org/sigs/web-sig" rel=3D"noreferrer" =
target=3D"_blank">http://www.python.org/sigs/web-sig</a><br>
Unsubscribe: <a href=3D"https://mail.python.org/mailman/options/web-sig/cma=
website%40gmail.com" rel=3D"noreferrer" target=3D"_blank">https://mail.pyth=
on.org/mailman/options/web-sig/cmawebsite%40gmail.com</a><br>
<br></blockquote></div><br></div>

--089e011604261e4e6f052dc9c1f3--

--===============7350659520008711350==
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

--===============7350659520008711350==--