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"><<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 <<a href=3D"mailto:andrew-g6StKjQqr+wpug/[email protected]= g" target=3D"_blank">[email protected]</a>> 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'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's why it's dict inboun= d and list of tuples outbound right now, and I just don'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 "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'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's point about http2'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'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==--