:-(
(split from URL)
So the main question seems to be: is the situation for DELETE the same as for GET, or maybe more similar to OPTIONS. As far as I remember, the latter is what we discussed in Prague 2019 (URL)
I might be wrong, but I believe the intent of the DELETE method is to just delete the target resource. Most of the cases out there that use a request body in the DELETE method, is to use 'delete' as a sort of rpc call to delete other, unrelated resources. While I think that this use-case is valid, I think that it would be better solved with: A PATCH request on a resource that represents multiple underlying entities, some of which ought to be removed. A DELETE request (without a body) on a resource that exactly represents the full collection of resources that should be deleted. A POST request with some custom media-type with delete instructions. Given that DELETE (unlike OPTIONS) is a non-safe method, and conforming services are likely to ignore request bodies and simply delete the context resource, I believe that DELETE should get the same treatment as GET: Emphasize that the request body has no semantic meaning. Improve the prose so there's less chance of misinterpretation (like GET)
I agree that using the payload to instruct the server to delete something other than the identified resource is incorrect, and we could mention that. There are uses cases though where the payload would add additional information about the deletion (keep version history? move to waste basket? archive?). In all these cases, this would be consistent with the overall semantics.
That's very theoretical. I suspect DELETE is very much in the same bucket as GET -- i.e., many intermediaries, servers, etc. will block a DELETE request with a body.
I disagree that it's theoretical. This would be a normative change from RFC 723x, so if you think that handling of DELETE is more like GET (than for instance OPTIONS), please prove it.
The onus isn't on me to prove that we can use DELETE in a way that isn't currently countenanced by the specs; if you want to open it up, do the work.
Now I'm confused. Currently we say: That doesn't imply that you can't define semantics for it though.
Example: URL
We can sit here forever and point out individual examples where developers are trying to use a body with DELETE. That's hopeless, particularly for examples like that redhat one where they are providing control data that needs to be in the header fields. In any case, sending a body with DELETE is not interoperable. Compliant servers will read and ignore them. Non-compliant servers will treat the body as the next request, resulting in request smuggling. URL
Yes, that is exactly what it implies. If you send a body, the recipient cannot use that body to have any meaningful impact on the request semantics.
Doesn't compute for me. An intermediary that discards a DELETE body clearly is broken, right? For an origin server to support certain payloads in DELETE requests has always been ok. If the user agents knows who he's talking to, why not allow him to send the payload? Where is the harm? All I would add would be a warning that even if you provide additional information to the DELETE request, it still needs to be aligned with the base semantics.
Nope. It's only required to read and discard the body.
Says who?
For example, URL
I know we get a lot of grief from those sentences about "has no defined semantics", but I am quite certain that they are trying to forbid using a body while at the same time avoiding message parsers that are dependent on the request semantics. HEAD was a disaster and I was trying to prevent any further damage.
IMHO: at the end of the day, this ticket is about making a normative change that will break some existing use cases, so it would need a better reason than "it might not work". But let's do a proper analysis first. You said that an intermediate MUST read the payload, but MAY drop it (right?). What part of the spec supports this? And is this specific to DELETE, or does it also apply to "PATCH" or "FOO"?
Discussed in Singapore; room sense was to behave like GET (body not allowed).


That's
says: I think this should be:
Discussed in Basel. The current ABNF defines as a special value which only invokes the semantics when it's the entire field value; otherwise, it becomes a field name (since it's valid according to the field-name ABNF) and effectively gets ignored (since it's not going to be in normal requests). An alternative way of looking at it is to say that it's a special field name that, when it occurs anywhere in the Vary field value, it effectively turns off caching, no matter what the rest of the field value contains. Waiting for data to see what implementations do. Either way, this needs some examples in the spec, since it's so special.
See some results . It looks like all browser engines will turn off caching if `.
Duplicate of ? See also .
NAME shhh, we're trying to inflate our issue stats.


Fetch and XMLHttpRequest have for the longest time used comma-followed-by-space (0x2C 0x20) as separator when multiple header fields are combined into a single header field. This is also what at least Firefox and Chrome do from code inspection: URL URL I think this is because of URL encouraging values to start with a single space and folks conceptually still seeing it as multiple values. Now URL has a much more explicit definition, which no longer allows for a space as far as I can tell, "breaking" with what implementations are doing. Most of the time this difference is insignificant, but anything with quoted-string or equivalent will be able to tell what was used if those configuring the headers like to play games. I'd like HTTP to either allow 0x2C 0x20 as an alternative separator (and have Fetch mandate it for browsers) or simply adopt 0x2C 0x20 as separator for everyone. I have some tests around this as well, but they only affect APIs, which theoretically could have a different non-HTTP-conformant view, but that'd seem really bad: URL See URL and URL for further context. cc NAME NAME NAME
Whitespace is allowed (and insignificant). Can you point at the actual difference between 2616 and 7230 which makes you think that something changed?
You mean when a quoted-string is broken into several header field instances?
In 2616 the same section states that values can be preceded by whitespace. Whereas in 7230 it only describes how to combine, without any mention of whitespace. Both sections are linked in OP. Yeah, also relevant for structured headers, which is how I started stumbling into this. If one client combines with a space, another without, and another with three spaces, you get subtly different strings and possibly room for security bugs.
This one? That's not specific to recombination.
I know...
Anne, I think what you're suggesting is to change: to: This is meaningful in some admittedly pathological cases, such as a header like this: Because the current text has a combined value of -- whereas most implementations will do .
So I think things are even more broken than I thought. A recipient that knows about URL and knows the header, might drop empty or whitespace values. So becomes (or maybe they'd reject it, depending on how the header was defined), but a basic intermediary would turn it into . The final recipient in that case cannot figure out what the sender meant. It seems to me that URL should only ever apply after combining header values, including empty ones, not before.
FWIW, the message was invalid wrt that header field already, so "figure out what the sender meant" doesn't make a lot of sense to me.
The problem is that "invalid" depends on whether the recipient knows the syntax, which is just broken if the recipient is allowed to combine before forwarding (which makes it "valid").
The only sensible thing to do is to always combine before determining validity.
See PR. NAME I haven't done anything to address your later comments; how do folks feel about adding a statement spelling out that consequence, either here, or in Considerations for New Fields?
I think explaining the issue would indeed be good.
NAME NAME - Are we sure what we really want to say "optional whitespace" here? Are CR LF or VTAB allowed?


We should explicitly tell them to reserve it.
I think the last comma is bad, but not enough to tweak it myself.


This is related to issue On the flight back from Switzerland, I spent time looking at the cache directives and how they differ from the descriptions in RFC2616. I worked out these problems and drafted a pull request, but I haven't checked whether we changed these deliberately for RFC7234, or if the distinctions just got lost in the rewrite. In any case, I think this is an improvement, but definitely needs reviews.
This ended up being an editorial change between drafts because the only normative changes were already noted for and , and this is just rewording what we had for .
From : Both state that a (depending on context private, shared or both types of) "cache MAY store the response and reuse it for later requests, even if the response would normally be non-cacheable". To my understanding, this does not intend to override the requirements from the "Storing Responses in Caches" section (URL) altogether. Instead, I would assume that it only refers to the condition "has a status code that is defined as heuristically cacheable" in that section (or, as it was stated in RFC7234, "has a status code that is defined as cacheable by default")? Would it make sense to amend the list of conditions in that section, appending to the "the response either..." second-level list: "contains a private response directive if the cache is not shared"?
OP here
lists some directives that allow responses with Authentication to be stored, but some of those directives' definitions do not mention this.
I think this should also be added for ; see .
I think this issue needs to be reopened and the specification text reverted to something more like what was in RFC2616. That spec specifically requires public be present to allow responses to a request with Authorization to be stored by a shared cache, regardless of must-revalidate or proxy-revalidate. This is not implied by those other directives.


… section;
Hi Roy, Please consider this reference for the privacy considerations section: Bujlow, T., Carela-Español, V., Solé-Pareta, J., & Barlet-Ros, P. (2017). A survey on web tracking: Mechanisms, implications, and defenses. Proceedings of the IEEE, 105(8), 1476–1510. Regards, Rob
URL
NAME has done a lot of work in this area, so he might have another suggestion. The referenced paper does cover a good amount of techniques that target HTTP itself, so I'd say that it's worth citing unless a better option presents itself.


NAME see revision.
The language for and indicates that they override the rest of the caching model unconditionally; as discussed in , that is too broad. Also, is often used even though the message is still cacheable, because developers misunderstand its semantics.
The text in question for private: to any other cache directives present, even if the response would not otherwise be heuristically cacheable by a private cache. lists one or more field names, then only the listed fields are limited to a single user: a shared cache [...] &MAY; store the remainder of the response message without those fields. I think there are two problems here: 1) "subject to any other cache directives present" is too narrow; the requirements in 3. Storing Responses in Caches go far beyond cache directives (e.g., method and status code cache ability). 2) The second paragraph omits any such condition. I think this can be addressed by replacing the clause above with something like "subject to the other requirements in [ref to section 3]", and repeating it in the second paragraph. We'd also need to add to the list in section 3 (probably below .
For public, we have: response even if it would otherwise be prohibited, subject to the constraints of any other response directives present. In other words, public explicitly marks the response as cacheable. Similar to above, I think it should be "subject to the constraints defined in [ref to section 3]. A note like this would also help:
LGTM.


NAME please review.
Roy noticed that we use a special meaning of "invalidate" and then define it pretty casually below. This can be improved.


header fields ought to define its own expectations regarding the order for evaluating such fields in relation to those defined in this document and other conditionals that might be found in practice. This should just be "HTTP", no?


The current section on CONNECT (7.3.6) in the semantics document refers to the proxy forwarding packets: Since the proxy terminates TCP, there is no forwarding of IP packets, but rather the contents of the TCP streams.
Well spotted! I'd even suggest "to blindly forward bytes in both directions ...". Too often I see people who imagine that packet delimitation is respected on both sides of a proxy and I have to tell them that it's just a uninterrupted stream of bytes that each layer decides to delimit wherever it wants.
I'd say that 7231 is self-consistent with the use of packet in 7230. If a change is needed, we should change wording consistently. Or, was this issue raised on the WIP core doc?
NAME this issue is being raised on the WIP core doc. The same text does also exist in 7231, but I consider them to both be in error. While we're updating the text for the core doc, let's fix the text to be clearer.
Thanks for the clarification NAME that sounds good to me.
Fwiw, the HiNT draft uses the terminology: blind forwarding of IP payloads, UDP datagram payloads and TCP/IP packet payload.
HTTP/3 says:
NAME that text looks good. Something along those lines, but that also works for HTTP/1.1, would be right for this core doc text.
Maybe just replace "packets" with "data"?
So as mentioned above in , while having a look at the latest draft I was struck again by this "packets" there, and even forgot about this old issue. Pinging again. I suggest that we change "forwarding of packets" with "forwarding of the byte stream" so that we can close these issues.


URL This sentence describes cases where the selected representation exists and has an entity-tag. Shall we also specify that "if the selected representation does not exist or does not have an entity-tag, then the condition is false"?


P-A is as: This seems really odd -- P-A is not generally used in a way that's specific to a single target URI.
I think it's scoped to the request; i.e., if the client retries the same request with appropriate credentials, it's likely to succeed; we can't say much more than that.
FTR, the text we have is inherited from .


Text taken from existing statement in Location.
Ah, makes sense, of course. Thanks NAME
NAME - can you check again?
2616's definition of said: 7231 dropped that, thanks to . We should probably restore it, given it can cause misconceptions like .
NAME do you remember why you removed that text?
Yes, the requirement moved into the general section on all URI-references. That is not a special case. And, no, its presence or absence would have made no difference to the referenced bug report. If either one of them had correctly followed the spec, they would have been fine. Instead, npm sent a special value without a special scheme, and Cloudflare marked that for rate limiting based on incorrect assumptions of bad behavior rather than the actual specification. Excuses happen.
NAME - I wasn't talking about the actual bug; I was talking about NAME -- someone who has implemented a very good HTTP engine -- misinterpreting the spec in that comment because it was reader-unfriendly. That should concern us all, because if he and implementers like him misread the spec so easily, it will be mis-implemented. And, the fault here is definitely not with him; it's with the spec. It's not reasonable to expect people to hold the entire specification series in their heads as they interpret each phrase and requirement, especially considering that in most renderings it's not cross-referenced (and even where the renderings support it, we don't cross-reference consistently). I understand that we need to be terse sometimes, and that it's reasonable to have expectations of our readers. But, when we use arcane terms and overload widely-used terms (even if incorrectly) to the point where the only people who understand the spec on a good day are you, Julian and I (and on a bad day, just you), it doesn't do anyone any good.
I think there are two ways to resolve this: 1) Link back to the URI section in each case where it's used, and adjust language to make it clear that there are requirements there 2) Add language in each case where a URI is a protocol element, and state how it's resolved I think I prefer (2), because is vague about how it specifies this: Since Section 2 is about HTTP URIs in general -- not just as protocol elements -- it's not clear what the scope of this statement is. It's also not a requirement, which doesn't seem good for interoperability.
Waiting for to land.
Places this will affect: Location Content-Location Referer
I still don't see any reason for this change. The spec already states how to do relative resolution in general, which it must do because it applies to all header fields (not just the ones we define). Saying it again on every occurrence of a relative or partial URI is just adding length to the spec.
We already said it for Location, and the amount of added text is minimal.
... and it's also said explicitly in . It may be obvious to you, but it's pretty clearly not to many implementers.
The only confusion has been our change in 7231 of the Location field to allow relative references. I am not aware of anyone ever being confused about the target URI being the base URI for all header fields, but I can live with more text if it says that consistently. To reiterate, this entire issue is based on a misreading of a completely mistaken assumption about the field content of "Referer: install" being flagged as a potential security issue by Cloudflare because it is unusual, not because Cloudflare somehow might not have been aware that the syntax is allowed by the spec as a relative reference. It's defense by spec-lawyering. These changes would not have changed Cloudflare's algorithm and would not have convinced npm to choose a more common default. Actually talking to their own CDN before deploying an HTTP change would have helped. Testing would have prevented it entirely.
NAME is right that the prose needs to be in sync with the actual ABNF. Will update the PR later today with a proposal.


NAME the ABNF is not the source of truth; as discussed, it's the recommended generated form. We have prose in that we use to do things like explicitly allow LFs to be separators and folding to be performed. Given that there is confusion, interoperability issues and security issues around bare CRs, a clear requirement seems proportional - especially when the ABNF does not specify error handling. I could see an argument to downgrade the requirement relating to generation to a note that it's not allowed, and I could see broadening the language in semantics to say that CRLF and LF are also not allowed.
For field values (Semantics), we clarify that these are illegal to generate. For recipients, we can say that for error handling, rejecting or converting to SP is common. Not sure what else needs to be said in Messaging.
I think that the security aspect justifies a new requirement; how about "MUST either reject or remove; suggest replacing with SP"? I was thinking about outside the field values -- mostly in the request-line and status-line. That said, I agree it's much less of a concern there, and I'm OK with dropping it if you think it's not worth it. I'll update the PR if you think the above is workable.
s/MUST either reject or remove/MUST either reject or replace/ ...I guess. Yes, that sounds right to me; although there might be pusback on the MUST (me neutral). The part for Messaging I believe deserves a separate issue and discussion.
NAME I'll make a change note in Messaging. WRT Semantics, the adjacent text about folding effectively deals with LF and CRLF. If you want to go to the trouble of separating into two issues and two pull requests, feel free. I'd rather just get it closed.
/me looks - NAME it already is called out. Please re-review.
On my agenda for today.
opened for field values
Splitting the issue was king of intrusive, sorry for that. The changes for [Messaging] have been merged. For [Semantics] please see URL
Popular clients handle LF, CR, and CRLF as newlines. HTTP only defines CRLF. Previously: URL
To clarify, this is about the CRLF in the HTTP-message production.
Covered here: URL ... but I agree it could be more visible (e.g., in 3).
And clients also accept lone CR. It seems worth testing either that they reject (network error) or adding that.
NAME see - in situ, see URL I'm still not sure it's obvious enough to someone reading in isolation; thoughts?
NAME that text does not treat CR without LF as a newline, unless I'm missing something. That text even seems to suggest that CRCRLF would be a single newline, whereas I'm pretty sure it ends up being treated as two newlines.
NAME I'm pretty sure CR alone is not valid, because I remember such a discussion a few years ago by the time haproxy used to accept this, after which I removed support for this. CRCRLF could at best be considered as a CR at the end of a line, though normally it's not a valid character there. It may possibly be replaced by LWS though.
Just found it, its in RFC7230.5 : URL Although the line terminator for the start-line and header fields is the sequence CRLF, a recipient MAY recognize a single LF as a line terminator and ignore any preceding CR.
Right, I realize it's not valid, but I also know that clients nevertheless accept it, which is why I raised this.
All clients?
If they don't, they're not interoperable on the Web as we know it.
The Web as we know it does not contain any CR-only line-delimited protocol services other than those deliberately attempting response smuggling. The protocol specifically forbids bare CR as a line delimiter, since that is known to not be interoperable with the vast majority of protocol parsers that exclusively check for LF and ignore CR. This was a big deal in 1994, but even then it was obvious that CR-delimited messages wouldn't make it through proxies. Nobody has objected to it since OS X was released and the last of the native Mac servers disappeared. If some browsers interpret CR as a line delimiter in HTTP protocol fields (other than payload content), they have security holes that should be fixed. No change to the RFC is possible here; we can't make changes that introduce new security holes to previously compliant parsers.
I wrote some tests for this: URL Suggestions for more tests appreciated. Firefox seems to generally take the CR and include it in the value of whatever preceded it (reason phrase or header value, despite those not allowing this character). Chrome and Safari treat it as LF in those places, but they do not allow two CRs to end the header block (network error in Safari, empty body in Chrome). It does seem that a stricter stance is possible here, given the intersection of the results. cc NAME NAME
If we can be stricter here and just fail on CRs in headers, that sounds good to me. That having been said, I think changing behavior to anything but just rejecting the response would be worse than the status quo (Treating CRs as part of header values, for instance).
Yeah, it seems like CR CR could be treated as a network error at least. CR "after" reason phrase or individual header is less clear. But I agree that making CR part of the value isn't good.
Regarding at the end of the line, we currently say?


These "(or laters)" don't seem to be accurate.
Suggest "(or later minor revisions of HTTP/1)"


changes to -messaging pulled from URL
I'll go ahead with this one as we already reached consensus in the original PR.


this is the part of URL related to -semantics
Continueing the discussion from URL Looking at the next text in context: To me it's unclear why we are calling out bare CR here, isn't the situation the same for LF and CRLF?? This also is not a new requirement, the ABNF does not allow CR and friends in field-value, and in 3.2 we say "A sender MUST NOT generate protocol elements that do not match the grammar defined by the corresponding ABNF rules." The subsequent paragraph talks about whitespace, and it may not be clear to everyone which characters we are referring to here (not the ones listed in Section 1.2.1 "Whitespace", correct?)
Proposal:
NAME ?
(forked from )
A bit iffy given the sentence above it, but okay.


Status code 308 is missing from the list in paragraph 2 of Section 9.1 of Semantics: "Responses with status codes that are defined as heuristically cacheable (e.g., 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, and 501 in this specification) ..."


It might be worth checking that clients indeed treat it the same as an unknown value.
That's an interesting question as well; but it seems to be orthogonal to this issue. Handling content codings is tricky (such as wrt ordering, repetition, and unknown encodings), It would indeed be good to have tests.
-> move req into field definitions
fixed by


These are just the cherry picked moves from that are moving sections to Semantics.
created issue for this
See


In 416 status code section, remove duplicate definition of what makes a range satisfiable and refer instead to each range unit's definition. In sections on bytes ranges and Range, clarify that a selected representation of zero length can only be satisfiable as a suffix range and that a server can still ignore Range for that case.
Regarding byte ranges, an empty (zero-length) representation is unsatisfiable according to section 2.1, but not unsatisfiable according to section 4.4 if the first-byte-pos is zero. I would like to see an update to the RFC which explicitly resolve this self-contradiction in whatever way seems appropriate. The following is one suggestion, but there may be others: I would like to suggest explicitly specifying that an empty 200 response should be returned in this case. It is the simplest solution to the current self-contradiction in the RFC, since it is a valid response anyway (if the server chooses to ignore the Range header), clients already handle it properly, it provides all necessary information about the representation to the client, and stating it explicitly can prevent subtle edge-case pitfalls in both the RFC and its implementations (as opposed to more intricate solutions). Perhaps the following can be added at the end of section 3.1: "If all of the preconditions are true and the target representation length is zero, the server SHOULD send a 200 (OK) response." (someone in the discussion preferred this to be a MUST, but the SHOULD might be more in line with the previous sections and backward-compatibility if some implementations resolved this in some other way.) I raised this in the mailing list a while back, and it got some discussion and support but did not get officially resolved. More recently I reported it as errata but it was rejected as not being an erratum and redirected here (I apologize - didn't realize issues moved to github, and still not sure what the distinction is :-) ), so here it is, raised again. All suggestions and feedback are welcome.
So how do we get this fixed? There was a discussion about it in the IETF mailing list, in which others confirmed the issue. I opened an errata, but it was closed saying it's not an errata. I was pointed here to open the issue, but got no response in 9 months so far. What can I do to get a response or to help move this forward? If the powers that be don't agree that the issue requires fixing, it would be nice to get such feedback explicitly and discuss it. If this issue tracker is inactive and the issue should be posted somewhere else, I'd be happy to do it, just point me in the right direction.
We're not currently working on a revision to this document, so an official answer won't be forthcoming for a while. In the meantime, the best thing to do is to discuss it on list, taking the advice you get there. See Roy's response in particular: URL
Just looked this up to see if it's been forgotten... can I assume from the new labels that it's on someone's todo list and will be looked at eventually, even if it'll take a while longer? (btw the link your referenced actually contains another bug, so I'm referring to both, i.e. the whole discussion).
NAME Thanks for resolving the issues! Better late than never :-) Indeed now there is no longer a self-contradition in the spec, but I'm curious, why did you change your mind since the discussion in the link above, where you seemed to prefer a 200 result for an empty resource (even suggesting a MUST), to the current fix which leans towards the 416 by defining it explicitly as unsatisfiable (with the option 200 downgraded to MAY), or at best makes it a tossup which option servers will implement? Did you have any specific pros/cons or use cases in mind? I guess I still prefer a 200 as the simpler and more straightforward solution :-)
An implementation can choose to send 200. Making that a SHOULD or MUST would be a new normative requirement that isn't justifiable for interop.
ok. Thanks again!


is a bit odd; unlike its peer sections, it's not a field name, it's a general concept. Then 10.1.1.1 goes on to specify how date formats in HTTP work generally, while 10.1.1.2 is the Date header. Given that we now have a section for generic syntax, I think it makes sense to promote 10.1.1.2 up a level, moving 10.1.1.1 out to an item in 4.4.1 (Common Field Value Components).
Discussed; makes sense.


... for If-Match and If-None-Match.
URL to special-case "*" as top-level construct.
Also need to fix things like to something like
Discussed; intent is to add a note at the end of each section pointing out that the behaviour of multiple/mixed stars is undefined, and that this is a lame way to specify a field.


Leaves registration of "" for .
Yes, seems to be a bug in bap. Will check.
it uses "" / #vary but "vary" is a token, and token allows "" anyway. Also, see .
In particular, "" is a valid field name. We probably should reserve it in the registry.
(CORS has an issue like that as well, including for a method; see the note at URL)
Proposal: vary-by = "" / field-name Vary = 1#vary-by Then state that if "" appears, no "real" field-name is allowed to appear as well (for backwards compat). Do we need to discuss cases like Vary: , ?
I don't see why that is an improvement.
I thought we were going to reserve and define its meaning in prose...
I.e., it should just be
which implies registering "*" as reserved field name, right?
Yes. That's
Discussed; will create a PR to move ABNF and prose to list-based.
Do we need to list that as change from 7230?
Probably a good idea; will commit to master and link here.
hit the wrong option


I got distracted by old text and revised the introduction of semantics.
The introduction should reference the currently defined wire formats (1.1 and 2, also 1.0 maybe). We also need to figure out whether and where to mention differences: expect/continue transfer codings status phrase
Also, the current introduction to all three documents says: That needs to be adjusted to something like:
HTTP/1.2? Is there something you need to share with the working group, NAME
I think (but am not sure) that this has been covered by the changes made in Maybe NAME and NAME could have a look and see if the short HTTP/2 and HTTP/3 descriptions need more flowers.
I think that the number of flowers (->0) is entirely appropriate and I would be happy with those descriptions, with maybe a small tweak to the HTTP/3 text.
I left a review; once we resolve comments on the PR, I think this can be closed.
Some nits, but I like the direction generally.Awesome!


Vary is described as: 'Host header field' is redundant; the target URI has that information already (and correctly) included.


As part of the discussion about the Encryption specification we discussed how Content-Encodings can or should take parameters from HTTP headers. The consensus was that they shouldn't. Whatever information a C-E may need should be inside the body of the object, just like the GZIP header etc. We should document this as a rule, if we ever do a HTTP[1].ter
+1, except for the constraint: "when possible". In the case of the encryption coding, it's clearly necessary to have the actual key information needed for description outside the payload.
we can add something to URL
I'm fine with this, but I'm also fine with closing with no action. I'm not sure what value it's really adding, since it's so vague, but I'm not sure what else can be said.


Historical note: HTTP 1.0 arguably specified the "abort request if the client half-closes" behaviour, see the last paragraph of URL, two pages down, just above URL This behaviour was implemented by several widely used HTTP servers; I worked on a firewall product at the time, and we had to take great care to make sure we handled TCP half-close correctly... The "arguably' is that RFC 1945 says "the closing of the connection by either or both parties", but sending a doesn't really "close" the connection - that requires either a or both ends -ing the other end's .
The HTTP RFCs say nothing about the expectations around half-closed TCP connections. In practice, I haven't seen any HTTP client in the wild send a request, and then send a FIN () while still waiting for the server's response. Because we haven't see any clients do that, as of Go 1.8, Go's HTTP server is starting to make assumptions that reading an EOF from the client means that the client is no longer interested in the response. (reading EOF being the closest portable approximation to "the client has gone away"). But in URL, a user reports that they have an internal HTTP client which does indeed make a half-closed TCP request. It would be nice if the HTTP RFCs provided guidance as to whether this is allowed or frowned upon. I would recommend that the RFC suggest that clients SHOULD NOT half-close their TCP connections while awaiting responses. Because nobody else does, empirically, and relying on reading EOF is a useful signal for servers. /cc NAME NAME
I've maintained a server in the past that received the same bug report. As a matter of compliance I decided the client was right - EOF is a way to delimit a message (they were using it to stream request bodies without chunking). But as a matter of practicality I didn't fix the bug because, as you indicate, ignoring EOF in practice means a lot of useless buffering ending in RST or timeouts.
NAME oh, interesting. And disgusting. I hadn't considered EOF being a means to end an HTTP/1.0 POST. Perhaps I can change Go to make an exception for HTTP/1.0 requests with request bodies.
NAME but NAME points out that RFC 1945 (HTTP 1/.0) says: So using a half-closing a TCP connection was never a valid way to signal the end of an entity body.
This is a pretty important question. Today, it's hard to spec out how cancellation works with REST. I suspect the proposed spec change will break some users. I wonder if it's possible to measure the impact with real traffic, from the server-side, e.g. the success rate of response completion after a half-close is received. I am happy to run some experiments ...
Here is a example of half-close connection in the wild, Livestatus. Livestatus is a broker for nagios. To use it via sockets you have to make the query, ex. and the close the write channel. After this, the Livestatus returns by the half-closed socket the results. Example in Python The important snippet is this, when closing the Write channel of the socket: Are there any workaround for golang? Source: https://mathias-URL
NAME Interesting. But is that HTTP? I see examples like the following on the web page. It does not even look like HTTP/0.9, though I am not sure what the proper syntax of 0.9 is.
It could be with unix socket or tcp socket. My fail I only read TCP, i did not see the repo is http :s. My bad, sorry, I came from another issue that was speaking about TCP without the http specification..
Hello, everyone! I would like to make a case for HTTP/1 disallowing half-closed TCP connections from the client. What I mean by that is that when an HTTP/1 client shuts down their writing end of the connection (when they send a TCP frame with the FIN flag), that the server can safely assume that the client lost interest in the unsent remainder of the response. On the other hand, if the server is required to support half-closed TCP connections from the client, in other words if the client is allowed to send a FIN after sending its request and it still expects to receive the response, then the server can only assume that the client lost interest when it receives an RST from the client. To be able to treat an incoming FIN as an indication of the client's loss of interest has advantages for the server: The server can free up resources earlier, upon the reception of the FIN, rather than having to wait for an RST a network round-trip time after sending a data packet. The savings are most pronounced when dealing with responses that trickle information down slowly as a form of long polling. Some stateful firewalls (NAT) between the client and the server drop packets for connections for which they no longer have state, rather than sending back RSTs. The RSTs thus never make it to the server, the server continues trickling down information until the lack of ACKs causes its window to fill and eventually a write to time out. Server resources held on behalf of a client who lost interest are wasted resources. I believe that there would be little to no disadvantage to the client. Furthermore: HTTP/1.1 encourages the reuse of a TCP connection for a subsequent request. Request message bodies are framed using or : "The presence of a message body in a request is signaled by a Content-Length or Transfer-Encoding header field." ( URL ) TLS 1.0 explicitly precludes half-closing at its layer: When one end receives a "closenotify" alert, it is required that it "respond with a closenotify alert of its own and close down the connection immediately, discarding any pending writes." ( URL ) Thank you.
A half-close has never been an indication that the client isn't interested in the response. It only indicates that the client isn't going to send any future requests on that connection. Since HTTP/1.x is defined to be independent of the transport, I see no reason to specify half-close – what matters is that the request message be complete. A server is not obligated to send a response, regardless.
Yeah, but TCP is a pretty popular choice. I think it's worth clarifying what this part of TCP means for HTTP. This bug exists because implementations are disagreeing on what it means. We're looking to a spec for guidance.
It's pretty hopeless at this point. I propose we clarify that half-close means nothing to HTTP/1.x in this spec, i.e. it's not a cancellation. If any http/1->http/2+ proxies send a rst stream when receiving a half-close from the client, it's a bug.
The problem with "clarifying it for TCP" is that HTTP runs on any transport with connection qualities and finding a word that means half-close for TCP doesn't always translate into some other transport or session-layer's meaning of half-close, but … I will try to find a way to do that when we get to the whole "what do we mean by a connection" rewrite in the semantics spec. In any case, regarding the original question: Go should not interpret an EOF on read as implying an EOF on close. Even if we don't see that as common in standard practice, there are probably thousands of deployed C applications that distinguish the two states; they won't work when some poor soul tries to port them to Go, and you'll be reliving this discussion on a regular basis. For example, IIRC, the first conversation I ever had with NAME (in 2000) was about using half-close to end requests in iCAP. It happens a lot more frequently in private hacks that are merely using the HTTP libraries for some other purpose.
in bkk: no strong consensus. mike bishop to see if he can identify clients that are using half close actively. agreed scope here is h1/tcp
I don't think there are any clients currently using this, but I think it would make sense to add guidance stating that half-close does not have any semantics, for all versions of HTTP. Having servers not kill half-closed connections may allow innovation down the line, and I don't think giving this guidance is risky
I've seen that quite a bit in field with monitoring scripts involving netcat, as well as data transfer tools. It's a bit less common nowadays since wget and curl are everywhere, but the usual stuff used to be this : host:$port | grep -q OK host:/d' > acl-URL In haproxy we don't do anything specific with half-close, we only rely on the end of message, unless the admin specifies "option abortonclose" in which case a half-closed client connection will be aborted if the server has not started to respond. Also there is no real value in killing half-closed connections. Often people who want to do this mix up the end of message and the end of connection and tend to believe that if the connection is not aborted, there will be no more opportunity to do it. But in fact if the client really aborts, the server will receive RST in response to some send() and will be able to detect the close. I would say that : half-closed (shutdown(SHUT_WR)) is a graceful shutdown (i.e. "nothing more to say"), signaled on the wire with a TCP FIN and detected on the server as read()==0 abort (close()) is a real connection abort (i.e. "stop sending this to me"), signaled on the wire with a TCP RST and detected on the server as send()==-1 The only case where you don't know is until you've started to send(), which explains why haproxy uses its option to decide what to do before receiving the server's response. I'm just realizing that we could even suggest to send a 100-continue in response to a half-closed connection to probe the connection!
What I've heard back from Microsoft folks with access to old emails is that we've seen half-close behavior from: .NET 2.0's HTTP implementation An IBM Java client, about which we have little additional detail Obviously, these are old clients with negligible share. However, that also illustrates the risk: old clients will not be updated to comply with a new spec.
Go's HTTP package uses EOF from clients to mean "the HTTP client is probably no longer interested in the server's response". We use it to notify callers of the HTTP server who've registered their interest in knowing when the HTTP client is gone (especially one reading a long-polled response, like Server-Sent Events). Notably, we want to know this immediately upon a FIN, without waiting for a write to fail. (We might not have anything to write for some time.) While we might ideally use OS-specific TCP stats kernel interfaces to distinguish FIN from RST, we support a dozen+ OSes and the basic interface we can rely on is EOF on FIN. There often isn't a better userspace API available to know the TCP state. I'd rather the HTTP spec say that clients should not half-close TCP connections, as some servers may interpret a half-closed connection as a client that's no longer interested in the response. Go has a package that lets you do low-level networking-y things. Anybody porting low-level C could port to that. The concern for this bug is about Go's behavior, not its package.
Hi Brad! You must not resort to using the OS to distinguish between the two because you don't need to know that. As you say it's system-specific. And until you send anything you're not guaranteed to get an RST anyway. The problem you're facing is that you're acting as a proxy between the client and the application. You need a way to let the application know that the client indicated that it stops sending, and only the application can decide if it's an indication of end of transfer or of client abort. Sometimes the application will decide that both are equivalent and that's fine. Of course when you get a notification of error via an RST, it's pretty clear and unambigous. If I may suggest, "just" pass a shut_read info in one case that applications are free to interpret as aborts if they want, and an abort or close info when you're certain it's closed. But really any network-based application must be able to tell the difference between half-closed and full-closed otherwise it's deemed to either abusively close on regular half-close or ignore real closes sometimes. In practice people tend to see TCP as a bidirectional stream while it's in fact two independent unidirectional streams. The only link between the two are the ACK numbers passed along packets to confirm receipt. But FTP servers for example are well used to seing half-closed connections since the data channel can be half-closed during the whole transfer.
NAME Go's HTTP package has supported its API since 2013-05-13 and the means it's not going away. We can improve the implementation, but we can't pretend the problem doesn't exist and remove the feature. It came about because it was frequently requested. Authors of HTTP server handlers want to know when people close tabs in their browser, etc.
NAME OK that's perfect. Then it's more a matter of clarifying what each event means and what shortcuts may be taken with what impacts. In practice it's fine most of the time, it's just that it's important to be clear about what this really means. For example it's fine to say "you can reasonably assume that a close notification indicates a closed tab and that you can abort an ongoing operation if your application is designed to work solely with a browser, but a more robust application should consider that it only indicates the client has nothing more to send and that the server must close just after sending the final response ; specifically, some scripts or API clients may induce a close event immediately after sending a request and while waiting for a response".
Discussed in Bangkok; we need to collect data about behaviour.
As an extra data point, both SwiftNIO and Netty treat receiving EOF on read as an indication the client is no longer interested in the response. We're definitely not happy with this: from our perspective, clients should be able to send FIN without us giving up on them. I'd be in favour of wording to disincentivise servers from doing what we (currently) do.
ietf104: significant interest in documenting somethinghere. at least "client should not do this" - hummed the question of discouraging the server from closing connection on rcpt of fin. a decent support for that pr.
There seems to be a really simple hack for differentiating FIN/RST. As NAME noted, a write will fail if a RST was received. This issue only applies to HTTP/1.1. Therefore: upon read-EOF, immediately write the "HTTP/1.1 " of the response line. If that write fails, you can safely abort generation of the rest of the response, because it was a RST. Or does this not work on certain platforms?
There are also various OS level options. Both epoll and kqueue can be used to distinguish FIN and RST, so it’s usually a matter of distinguishing the two cases in higher level APIs.
Good that this issue is still open :) Since the server always knows what works or not, writing a first-line header in response to FIN does allow most of the servers to detect aborted clients immediately. Maybe the spec can just clarify that FIN (half-close) should not be used by the server to cancel the request unless the server has a way to detect that the underlying TCP connection has been shutdown (i.e. the peer has gone away).
Reading through the discussion, a couple of notes; We already talk about half closed connections on the server side in , so talking about them on the client side isn't prima facie out of scope. It might be helpful to explicitly note that requests are not delimited by half-close in . That's not a normative change, just a clarification, and it aligns with broad implementation. It would also satisfy the desire to document "client should not do this" at least in that case. It seems like the best we can do on the server side (in terms of interpreting FIN from the client) is to document that some servers assume it to be a loss of interest, but this may not be reliable in all cases, and should not be relied upon by clients.
^ PTAL
In 9.6 "tear down", after "If the server receives additional data from the client on a fully closed connection, such as another request that was sent by the client before receiving the server's response", I'd add "or the message body". The RST problem is far more visible with POST requests that servers reject due to authentication, redirects, lack of cookies etc, where servers are tempted to respond and immediately close without draining the entire request message. Regarding the questions above, I'm still seeing a few possible hints/workarounds for server implementers who really want to have good interoperability and good assurance that a tab was closed. One hint is to emit a "100-continue" interim response in response to a half-closed request if the request was made over HTTP/1.1. If the client is still there, it will have no effect. If the client has completely closed, this one will trigger a reset from the client which will be detected by the server. The other solution is to consider that if a client sent a request in HTTP/1.1 without "connection: close" and finally half-closed the request side, it is extremely unlikely to be a simple implementation and that it can be assumed with good confidence that the client really wants to abort request processing.
Hey Willy, Would something like this do the trick? I'm a bit wary of putting this in the spec, since it's so specific and advisory. What do others think?
I agree both with the text and your concern. Maybe we can enforce the fact that it's absolutely not a spec and just a hint by saying "... a server that really needs to distinguish these cases could for example send a 100 (Continue) non-final response if it hasn't yet sent a final response". This way it's clearly worded as a hint to work around existing API limitations and to remind developers that determining whether a client closed a browser window is not rocket science over TCP.
I would implement something like a zero-byte chunk, or a small mount of dummy data (safe to the MIME type such as JSON), which could also help "keep-alive" a streaming response without introducing a non-standard C-T. If a server has already generated the C-L header, I would just let the request run to completion. Or are we concerned about proxies buffering the response body, because 100 will always reach the client immediately?
BTW, I actually plan to implement some sort of cancellation support soon for web frontends behind URL; and I could help report some data wrt the detection mechanism, with or without the app responding to the cancellation event.
You can't send a zero-byte chunk before headers (and even less data of course). The only other reasonably interoperable thing you could send before headers to probe the connection would be a CRLF since most agents will ignore them before a message. Another approach would be to start sending "HTTP/1.1" without the status yet (or just "HTTP" without even the version), but it can be trickier as it will require to remember that this part was already emitted. Now after the headers it's different, you're already sending response data so you don't care, you'll know very soon if the client is still there.
I was wrong. What I proposed (i.e. writing extra body bytes) only works for frameworks that generate headers immediately without waiting for applications to write any data (which might include errors but as application payload). Re: 100-continue response, I noticed that the following restriction stated in rfc2616 was removed from rfc7231. "An origin server SHOULD NOT send a 100 (Continue) response if the request message does not include an Expect request-header field with the "100-continue" expectation. " Curious what's the background for this change.
I suspect the reason was the prevision for new 1xx status codes, that just clients can remap to pure 100 when they don't know them. Note, I proposed 100 but any 1xx (except 101) would fit. For example we might instead send "102 Processing" (rfc2518), which could be even more suitable and possibly less confusing.
I could live with this. Will report back how frequently we are seeing FINs with a pending http/1.1 request on the client side. Yes.


evaluating false on a duplicate change request sending 2xx without validator for reasons unknown.
Hmm, of course, now I found another related message in my archives that prompted me to remember why the requirement was added. I should probably rewrite the paragraph (without that requirement) and describe the edge case as a note.
RFC7232 in URL has the following clause: It doesn't really explain what security or performance considerations are leading to such a requirement, but it calls for a lot of infrastructure and design work to implement it because that logic can be implemented only if the server is stateful. The stateless server cannot comply with such a requirement. See related mail list thread: URL Either RFC should explain why such logic MUST be implemented or relax "MUST" into "SHOULD" in that clause or remove that clause completely.
Should I submit an errata proposing to remove the following clause from RFC 7232, section 3.1: " In the latter case, the origin server MUST NOT send a validator header field in the response unless it can verify that the request is a duplicate of an immediately prior change made by the same user agent" It seems like nobody can recall/explain why this clause is there.
I finally found the original commit 303b82b12a53c170f6f755aaaf8840ac1240aa77
And the discussion motivating the change is under . Certainly the intent was to remove the constraint that an error be sent when a duplicate request is made, so the extra limitations were to reduce edge cases.
It is not an errata. This is the right place to discuss it and either find a better wording or strike the text.
Thanks, NAME for finding the original commit and your response! Sending response for repeating requests makes total sense. My issue is about a sub-condition of response that is stated in the RFC7232. In the original commit that you referenced that sub-condition is stated as: I think I understand the original recommendation not to send back. It would be better to replace with there though. But in RFC7232 that sub-condition clause is changed to: The reason of not sending with back is not explained in RFC7232 and nobody can remember why it is there or explain this requirement. Complying with this requires dev effort and extra infra since we would need to track immediate previous requests from each agent. Our API servers are light-weight and stateless so this is a huge requirement for us. Instead, we would prefer a way simpler approach of always sending back along with responses, but we need to comply with RFC7232 thus this discussion. So, the proposal is to do one of the following (preferred) Remove the following clause from RFC7232: (If aforementioned clause is kept) Explain the reason of not sending in that sub-condition (at least) Change to in that clause.
These requirements were motivated by a tiny edge case related to protecting partial updates after two clients simultaneously try a PUT. However, I can't remember if it was when one succeeds and one fails, or one or both responses are lost and they try again, or something like that, nor can I remember what difference was made by not sending ETag. Hence, I intend to remove the requirement as being too obscure to implement in a testable way.


We decided to move the version-independent parts of the definition of Content-Length to Semantics, but that calls for some new text to explain its semantics in general. For now, we have added (in crefs) the following text to the section on "Content-Length" in Semantics:
s/representation/representation data/?


These are probably just implementation bugs, but it's somewhat curious that no browser handles from the standard correctly. They all do handle correctly on the other hand. I'll create some manual tests for web-platform-tests, unless someone has a good idea on how to automate this...
At it's defined by and by with But in the it is: :confused:
What exactly do you mean by "but"?
You're right. My fault. I didn't read the correctly. Where is the alternative defined? Thank you for your assistance.
See URL and the links from there.
Thank you and sorry for the noise.
Basic manual test at URL including links to browser bugs (all browsers fail).
When I wrote tests around seven years ago, Konqueror was fixed to pass most of them. That seems to indicate that it's possible to implement the spec.
Oooh, can we convert those to web-platform-tests somehow, even if only manual for now? (I got some pushback from at least one Firefox developer on fixing this and given it's HTTP authentication I suspect most people won't be too enthused, but it also seems worth fixing as having separate parser requirements for any header between a single comma-separated and two headers is just bad and not really compatible with how HTTP is defined.)
Feel free to steal from URL ...
While it's possible to implement the spec, given that none of the browsers implement it and doing so won't really make anything possible that isn't possible now, could we limit to one challenge per header?
In HTTP, intermediaries are allowed to coalesce multiple field instances into a single one, no matter what the field name is. So if you have two header instances, it's legal to combine them into a single one. RFC 7230 made one exception for cookies, because they break otherwise. We looked at WWW-Authenticate and verified that no exception is needed here. So my position remains: implement the spec, or otherwise prove that it's impossible/would break existing use cases.
I'm the one Anne talked to. He's right, I'm not particularly excited about the idea of making this change - none of the browsers handle it right now, and with the ambiguity around commas in the grammar, making this change is on the higher side of the "likely to introduce terrible bugs" scale. Not to mention there may be intermediaries somewhere that depend on the current behaviour. Changing this could also result in interop issues there, which will be much more difficult to fix than upgrading clients. Given all that, this seems like a case where changing the spec would be more appropriate.
How exactly would those be affected?
Even if you change the standard, some browsers might still have to change their code as URL indicates that, e.g., parses differently across browsers. That doesn't really seem like an acceptable outcome whatever we do.
FWIW, that's a parse error according to the ABNF. EDIT: in the meantime I realized that the syntax is ok.
NAME : Currently one can embed a comma somewhere in the auth challenge. These will break if browsers change behavior. Given how long this bug has been around, it's difficult to estimate the effect of such a change. Both FF and Chrome have telemetry, but at least from the perspective of Chrome, we don't have much insight into many corporate or closed networks where middle boxes tend to be much more prevalent. The change itself is fairly trivial from a code perspective. And I understand that either option isn't great. However IMHO the reward doesn't seem to justify the risk of changing browser behavior here.
No, it doesn't, if the parsing is done correctly. Please give an example if you think otherwise.
I don't know, and that's what scares me. Intermediaries have all kinds of busted behaviour already, and changing the way the WWW-Authenticate header is parsed in practice (spec notwithstanding) could have unintended consequences (dropped as a malformed header is the first possibility that comes to mind).
It would be helpful if you gave at least one concrete example.
HTTP is not defined by browser behavior after receipt of a valid message. Even if five major browsers caught fire and imploded upon receipt of multiple challenges, that would only increase the need for those parsers to be fixed (somehow). We can't control the bits received. The easiest fix is to simply parse the field as specified, since that's what the non-browser UAs have been doing for ages.
NAME unfortunately I can't, as I have neither the time nor the resources to test even the most common intermediaries. I've just been around long enough to not trust them to not be doing something horrible. NAME your hyperbole is not at all useful here, thanks. I'm glad you're confident in all the major browser vendors being so perfect as to not accidentally introduce some corner-case parsing bug that is potentially catastrophic for the security of WWW-Authenticate. I would prefer to be conservative, and recognize the fact that this is the way the internet has operated for years (decades?) and we're probably better off taking the safe course of changing the spec over changing every single browser on the planet's handling of a security-sensitive header.
NAME What hyperbole? Changing the spec is not a "safe course", no matter how you look at it. There exist cases where multiple schemes are in use today. There exist many intermediaries that will, without question, merge those multiple field names into a single field value regardless of sender's choice to send multiple fields. There exist many clients (e.g., API clients) that currently support multiple auth schemes and choose one, which is the primary audience for this bit of the protocol. The only question here is what should a browser do given the same bits received. Regardless of that answer, the spec will not be changed.
OK, if the answer I give doesn't matter, and the spec won't be changed, then no point engaging.
We cannot change HTTP (for which there exist thousands of independent implementations) just because a few browser implementations choose to ignore a valid header field value. We can only make a change when all deployed implementations do the same thing, or when failing to implement it correctly is either impossible or known to be insecure. Servers compensate by not delivering the same options to bug-present user agents that they do for API clients, or rely on a TLS connection being sufficient to prevent most intermediaries from joining field values (which can lead to gateway/CDN issues, etc.). This has never been good for the security of browsers. They get stuck with Basic while the rest of the HTTP universe is using better auth schemes. Nevertheless, we can't change the spec to prevent header field joining, which deployed implementations have always done, nor can we disallow multiple auth schemes that current APIs depend upon. Hence, an implementation can choose to magically ignore some parts of the field and occasionally fail to support certain (usually more secure) auth schemes when an intermediary is present, or we can get past the FUD and just implement the field as specified. That is an implementation choice, not a spec choice.
FWIW, I believe there is some confusion about what a conforming client is supposed to do. Hint: it's not "splitting where a comma is". That's why I'm asking for examples.
NAME if I'm not totally wrong a is not allowed within a only in a (double) quoted string So parsing is not straight forward "splitting where a comma is".
NAME - that is true, but it is allowed in a parameter value (when using quoted-string syntax). FWIW, this syntax is common across many many HTTP header fields. A common parser library should do the trick.
NAME definitely, do parsing not by yourself. But I've no idea how many libraries/frameworks does it correctly beside of browsers.
Let me just gently remind the audience here that authentication if anything is possibly even more widely implemented and used in and by non-browser HTTP user-agents. Then, I could add that curl also doesn't parse these headers "correctly" and assumes multi-line. And I don't think we've ever had a bug report about it...
I believe this issue should be closed with no action.
NAME does "assumes multi-line" mean "only supports multiple challenges if they're on different lines"?
ah yes, exactly.
I think the options available to us are: Do nothing (i.e., close this issue without action) Include text advising that putting more than one on a header field line may not be interoperable Create a formal exception for (like Cookies)
I don't see why a formal exception is needed; the situation is different from Cookies (cookies do not work without the exception, but WWW-A does). My preference is (1), but I could be persuaded to do (2).
Does anyone object to (2)? If so, why?


Does this mean it's now valid to interleave HTTP/2 DATA frames and HEADER frames?
Does this mean we cannot implement this on HTTP/2?
The feature was removed during WGLC, but no -- it would have required a new frame type.
Okay, so chunk extensions remains a unique feature of HTTP/1 chunked encoding and there is no plan to expand that further?
Yes.
As discussed in and URL, mid-stream trailers (i.e., those that arrive before the end of the payload body) are interesting. A few things to discuss: [ ] What are some potential use cases?[ ] We recently stopped automatically combining trailers into headers, as that created a lot of issues. What about these -- are they yet again distinct from trailers as well as headers? Or can they be "downgraded" into trailers automatically? In other words, when transitioning from a hop that supports these from one that doesn't, are they just dropped onto the floor?[ ] Related - is the expectation that implementations will create separate APIs for these, or would it be that trailers are just available / writable early?[ ] What relationship does one of these have to the payload body? E.g., could I write one that "knows" exactly where in the body it occurs, so that it could sign a chunk of the body relative to it? Or could a handling implementation change its ordering in relation to body bytes?
Some preliminary considerations. Incremental checksums eg. Service management (eg. convey the ETA of the transfer, ...) Sending signatures of partial body (in mid-stream) has some complexities respect to sending a signature of the whole message in the header/trailer section, and requires a security URL trailers, when used for integrity can't be dropped without informing the user agent They probably need to be defined as 1#field-item because mid-stream trailers will be sent multiple times (eg. one per chunk) Whenever they are tied to the partial transmitted representation, they will eventually be unuseful when merged, unless they have some associative propertyThey will be especially useful when tied to a portion of the body They will be significantly less useful when not tied to a portion of the body
Potential use cases mostly limited to long-lived streaming traffic, i.e. long-lived "uploading/downloading" in-band signaling support such as load reporting, app-level flow-control, authn update etc Semantics trailers are a special case of mid-stream metadata, e.g. only trailers are able to convey the status of the entire transaction or the entire resource (body) our experience is that in-order delivery is useful and often assumed, since the underlying transport (for HTTP body) is in-order and reliable. Out-of-order metadata is likely a use case for connection-level metadata, IMO with the above assumption on in-order delivery, you really only need one API for delivering in-stream or trailer metadata Multi-part without in-stream metadata, you would have to use multipart (with all the overhead) for structured data, the original content-type can be preserved, e.g. JSON stream; and for media data, the content-type may have to be application/octet-stream
Copying over the questions from NAME over in URL, as they are good ones:
The semantic model of trailers is that they provide additional metadata that may (or may not) be useful to recipients but was not available prior to the initial body data sent. How the are useful and what they might contain would be defined by the field name. A recipient is free to drop the trailer metadata. A mid-stream trailer frame would have the same role in flow control as a HEADERS frame, which is none at the current time. The proposed frames would not have any specific position, but the values inside trailer fields might identify specific positions (on their own, regardless of framing). A cache would either drop the values or store them separately as trailer fields in the order received.
HTTP/2's flow control only cares about DATA frames. But all frames are subject to TCP's flow control. In HTTP/3, all frames are sent on streams which is subject to QUIC's flow control. Responding to the original question, I don't know what a "new form of flow control" would look like and I don't see how one would improve things.
What's the minimal change that would need to happen to semantics to enable this in a future version of HTTP (or an extension to an existing one)?
I think you would need to make "trailer part" less special, and simply say that a version of HTTP can define a way to carry additional field sections during or after the body. H1-H3 currently define a way to carry only one such block, but an extension could provide more.


reads: This seems to have the effect that 412 cannot happen as part of a 100-continue response, but instead, the entire upload body must be parsed for errors (such as ), and only if it is free of errors can the server return 412 (Precondition Failed). This seems unnecessary and wasteful of bandwidth, and perhaps a result of the fact that server-side validation of documents, including the 422 Unprocessable Entity status code, is a comparatively newer feature of HTTP servers. [1] If this is the case, consider relaxing this requirement so that 412 (Precondition Failed) is the last error tested before the request body is parsed. [1] See mailing list thread:


Need to talk about the on-the-wire scenarios; representation w/ vary vs without.
When making the edit above, I started to wonder what the best strategy was to recommend: Use the most recent valid Vary field value (current text) Just give the one without a Vary field value the lowest priority Thoughts NAME NAME ?
This language is a bit ambiguous regarding whether the received response is included in those considered, etc.
On second reading this wasn't as bad as I thought; made a few small editorial clarifications.


: I think that MAY should be prose, and should also list retrying the request as an option.


The practice of combining list-form fields into a single value is widespread, and the document addresses this pretty clearly. However it never really says that this combination needs to be limited to a single field section. It's pretty clear that trailers need to be kept discrete, but there is nothing so direct. It's probably worth adding "within a field section" somewhere.
Agree, but I can't find the definition of "field section" neither in MESSAGING nor in SEMANTICS :)
I was pointed to URL which is good, but it doesn't really say that this combining only applies to a single field section (and yes, that is not a term that is defined in the document as far as I can see).
Thanks, this works nicely. Shame that you had to add a new term, but we already got that in QUIC.


We should really mention this, as it's common and can cause misunderstanding. I also am likely to need to reference it in .
Maybe add a minimal explanation of "collapse"?


We say that we don't restrict how other caches (e.g., higher-layer in the browser, back/forward) interpret cache directives, but I think it would be useful to give a bit more guidance here, as this causes a lot of confusion and interoperability problems (since the browsers still haven't sorted out the various other caches' operation). For example, we could give string guidance (non-normative) that should be respected by other caches.
All of these caches are in front of the networking stack and in theory might not even have all response headers if converted to a more optimal representation. If you consider JavaScript modules, they are de-duped based on their request URL in a module map. If the first response for such a URL had , we still wouldn't be making any further requests. The same goes for images, style sheets, and some other resources as I understand it and for some of these changing that would result in compatibility issues (or presumably functional errors in case of module maps). For back-forward in particular it might be worth reading URL There's a worry that an explicit opt-out could end up cargo-culted and make the feature unusable.
NAME that makes sense, I agree the current wording is too strong. How about changing apparent to or easily controllable by the user, it is strongly encouraged to honour basic control mechanisms like Cache-Control: no-store, as they indicate the resource's intent regarding caching. to: apparent to or easily controllable by the user, it is strongly encouraged to define its operation with respect to HTTP cache directives, so as not to surprise authors who expect caching semantics to be honoured. For example, while it might be reasonable to define an application cache "above" HTTP that allows a response containing Cache-Control: no-store to be reused for requests that are directly related to the request that fetched it (such as those created during the same page load), it would likely be surprising and confusing to users and authors if it were allowed to be reused for requests unrelated in any way to the one from which it was obtained.
I think that's good. Some of the caches I mentioned do cross page loads (e.g., images and style sheets). However, I think the statement about those is correct and we should be better about explaining how they fit in and make sense (and perhaps adjust if they don't).
It seems to me that cross-page loads are exactly the type of thing that a sender of no-store is trying to avoid. It is the type of flag sent on highly sensitive or volatile data. Images, stylesheets, etc which have cross-page relevance should not be using it.


says: What about multiple ?
I think the right approach here is to require adherence to the most restrictive directive received, but I want to write some more tests first.
OK, the . In a nutshell: No implementation follows the more conservative when multiple are received, either on the same line or separate lines If the directives occur on the same line, most implementations (except Firefox and Apache) prefer the first occurrence. If the directives occur on separate lines, the behaviour is about the same, except that nginx flips and prefers the second line. OTOH most implementations do honour a stricter directive (e.g., or in the presence of more liberal ones like ; the only exceptions there are nuster (a new implementation) and Fastly (this is a known issue). So it seems like the most interoperable thing to do would be to document that when a directive with an argument (like ) appears, the first occurrence should take precedence; however, conflicting directives (like and ) should defer to the strictest.


NAME It already is, this just changes how it's done.
My seem to indicate we might want to reconsider how . Of implementations that honour (two don't): none will consider invalid none will consider on two separate field lines invalid none will consider a duplicated value on two lines to make the header invalid if there are two header lines, all will consider only the first (and one, Safari, appears to use the min of them) none considers a non-numeric value to be invalid only Fastly and Firefox consider a non-negative integer to be invalid ... where invalid currently is required to be considered stale.


I believe that we said this could be merged when Julian's issue was addressed, which Roy's suggestion did, so merging.
Some guidance about how and if new preconditions can be defined would be helpful. See .


NAME - is Oct 1999 correct? (taken from Last-Modified)
Last edit is 1999 but was just a markup fix, original document is dated 1996-10-03. HTH,
This seems out of place, although I understand that versioning is very message-based. I'd suggest putting it in 15. Extending HTTP?
It's not about extending HTTP. The version number literally exists as a field of the message, or at least inherited by the context of the connection, and must be retained by recipients because of version-specific requirements. That's why we need to define both cases as part of the message abstraction.
Fair enough. Can we open the section with a sentence or two that says that it's a field of the message, to give that context? The current text is pretty abstract.


When I was restructuring Semantics, the paragraphs for defining when a message is complete stuck out like a sore thumb. I moved them to their own section and added a comment for later definition. This issue tracks that definition (editorial).


URL This seems to place a requirement on the server to serve enough of the representation that all satisfiable ranges requested are fulfilled. But that's actually a burden and makes range requests not as useful as they could be: a server might well not want to implement multipart/byteranges, which is an awkward format that can't be streamed without prior knowledge of what strings are safe to use as separators; responding with a single range is much simpler to implement. If all satisfiable ranges must be served, then, without multipart/byteranges, the only compliant options for responding to a range request with large distances between the requested ranges involve sending all of the bytes in between. Even reading the text as meaning that servers MUST NOT only serve a portion of the satisfiable ranges, client behaviour when faced with a misbehaving server is under-specified; the sensible options are re-requesting unfulfilled ranges, retrying without ranges, or signalling an error. Retrying without ranges may be wasteful, and raising an error seems overly fussy - and, if either of those is the better or even necessary option, that definitely ought to be called out. I'd be surprised if retrying without ranges or erroring was needed, because section 10.3.7.3 (Combining Parts) already deals with combining multiple 206 responses together. So, I think it'd make sense to make two changes here: An explicit SHOULD on clients receiving a 206 to check the ranges that they actually received and make further range requests if they still need any ranges which weren't included despite being satisfiable, which they can determine because Content-Range includes enough information to tell which were unsatisfiable and which were simply not fulfilled. Explicitly say that servers MAY only serve a portion of the satisfiable ranges.
It says "one or more" for exactly that reason. A requirement to send all would have to say ALL, so this is clearly not the case.
Wouldn't the text then be or something very similar? As presently written, I can't come up with a parse that unambiguously means that some of the satisfiable requested ranges may not be fulfilled - and, in any case, I do think the client behaviour on ranges not being fulfilled needs to be specced a bit more.
I read the current text as implying that in normal operation, the server will send all of the requested data back in some form; it might be in one range or multiple ranges, depending on its preferences and capabilities. NAME AIUI you want to rewrite this so that when a client sends (for example) requests for ranges 10-100, 500-1000 and 5000-6000, the server can just choose to send one (or two, in theory) of those ranges back, rather than all of them. That might be easier for the server in a number of ways, but it relies on the client recognising that the missing ranges need to be re-requested, one-by-one; effectively, it's a new protocol. As such, if you want to enable this new pattern, I think you'd need to signal support for it in some fashion from the client. That's out of scope for this spec effort; it would be an extension.
That is indeed what I'd like to have. I think there's definitely still room for at least clarifying the situation, given that two editors here read the text in two contradictory ways! Hmm, I don't quite agree. A well-behaved server would want to see support signalled before leaving some ranges unfulfilled and I agree that that would be a new protocol, but a malfunctioning or badly-behaved server might be ignoring the send-all-ranges requirement - I think that's especially likely to be happening in the wild given that the spec here is hard to interpret. Clients will still have to deal with that, and the spec can at least list reasonable options (re-request satisfiable-but-unfulfilled ranges, re-request the whole thing, error). Here's a new straw suggestion that (I think) doesn't change the required behaviours, just formalising and clarifying exactly what's required: An explicit MUST on servers returning enough of the representation to fulfil all satisfiable ranges. An explicit SHOULD on clients checking the Content-Ranges sent back, just in case a server is misbehaving, and list the three sensible options after detecting misbehaviour with MAY.
In normal operation, a server will try to send all of the requested information just for the sake of avoiding another request, unless it doesn't want to for its own reason that we have no need to describe. A 206 response is self-descriptive. A client cannot interpret the response differently than how the response describes itself. The client cannot assume it has all the requested ranges it requested. There is no need to require that a server send all requested parts. There is no reason for a client to assume it would receive all of the parts without looking at the response. Hence, this is not subject to an interop requirement. The text I'd consider adding is a note at the end of that paragraph, like
Alternatively, just add that requirement to the section on 206.
I think the most compliant server response, if it doesn't support multipart/byteranges, is to respond with the range 10-6000. Servers are allowed to send different ranges than the client asked for, but I think a server omitting some of the requested ranges can't really claim to be "successfully fulfilling a range request." The server's response needs to include the bytes the client asked for. That said, I think something like NAME suggested text would be helpful. I've seen clients get tripped up before when the server produces a different set of requested ranges, either by extending a requested range or by coalescing ranges. It looks like a rewording of the text at the end of 10.3.7.2, which would be appropriate to either replicate in 10.3.7.1 (you can't expect exactly the range you requested) or move up to 10.3.7.


We need to discuss this; prohibition at least semantically, and probably also strongly urge against accepting on the wire for security reasons (although somewhat version-specific).
Discussed; just need to align 1xx language with others.


IIUC httpbis-semantics changes the field name registry, thus updating BCP 90 / RFC3684. Is that correct? Should httpbis-semantics mention that? NAME
"obsoletes": no, because BCP 90 is also for email. "updates": yes, I think so. NAME
Hm; I suppose so, given that it's taking some of 3684's turf away.
Now does that make SEMANTICS part of BCP90?
I'm inclined to say no -- it modifies the scope of BCP90 to exclude HTTP header fields. Worth discussing more broadly, though.


: >A Last-Modified time, when used as a validator in a request, is implicitly weak unless it is possible to deduce that it is strong, using the following rules: I'm hearing that this 60-second window is problematic for videos, where clients often request a partial video segment within a minute of it being published (thanks to e.g., CMAF). Since those requests use , they require a strong validator. Should we revisit this, given that it is an arbitrarily chosen value by our own admission? I agree that some caution is necessary here, but a one-size-fits-all approach doesn't seem viable.
Discussed on call. Sense is to make this much more based upon the judgement of the implementation, rather than just an arbitrary number.
Suggestion:
NAME NAME - this creates a nested unordered list which comes out really strangely in HTML, please check. Maybe it would be better to have the two statements (that are nested) in a single list entry.


I think this should be something like "Message Framing and Incomplete Messages", and should be after the headers / payload / trailers sections.


This seems out of place, although I understand that versioning is very message-based. I'd suggest putting it in 15. Extending HTTP?
It's not about extending HTTP. The version number literally exists as a field of the message, or at least inherited by the context of the connection, and must be retained by recipients because of version-specific requirements. That's why we need to define both cases as part of the message abstraction.
Fair enough. Can we open the section with a sentence or two that says that it's a field of the message, to give that context? The current text is pretty abstract.


Now that we have three different places referring to the text on updating stored headers, it deserves its own section. In the process, I noticed that the current text forgot to mention that CC: private and no-cache can have arguments that affect header storage.
says: As per other discussions, this needs to be more nuanced; either a reference to 4.3.4, or new text.
The that no one is really doing this; is either converted to a GET on the backend, or it doesn't seem to touch the cache. I think the most sane thing to do is to refer to the rules for a 304 update, but make it clear that this is optional.
Could you clarify how HEAD is relevant for "Combining Partial Content"?
Arg, sorry, wrong issue.


"The following core rules are included by reference, as defined in [RFC5234], Appendix B.1: ALPHA (letters), CR (carriage return), CRLF (CR LF), CTL (controls), DIGIT (decimal 0-9), DQUOTE (double quote), HEXDIG (hexadecimal 0-9/A-F/a-f), HTAB (horizontal tab), LF (line feed), OCTET (any 8-bit sequence of data), SP (space), and VCHAR (any visible [USASCII] character)." Of these, only DIGIT is actually used.


seems very out of place. I could almost see it as content in 3, as a kind of introduction to the terminology. There are of course other places it could go, but the current location doesn't make much sense.
I moved the ascii art diagram back to the origin server section (where it came from in 7230) since it leads into the other diagrams.


As discussed on call, we need to say that PUT requests can contain response headers, and what that means.


I think we discussed this last week and Julian has pending changes to be made before review.
This just moves the ABNF, not the definition of the transfer codings.
This is the remaining ABNF production that Semantics imports from Messaging (for the definition of "TE"). Maybe we should move the production to messaging, reversing the dependency.
Discussed on call; worth a try.
URL out that there are a few more things to consider: Semantics currently claims there are regular parameters here, but transfer-parameter is special wrt BWS should we move the special case of "trailers" in the grammar into prose? In any case, what would it mean to have a ranking on "trailers"? Invalid, thus ignore? "t-ranking" seems to duplicate "weight"
Fine to merge, but shouldn't we also move the extensibility and IANA registry sections?


(again)
We say that we don't restrict how other caches (e.g., higher-layer in the browser, back/forward) interpret cache directives, but I think it would be useful to give a bit more guidance here, as this causes a lot of confusion and interoperability problems (since the browsers still haven't sorted out the various other caches' operation). For example, we could give string guidance (non-normative) that should be respected by other caches.
All of these caches are in front of the networking stack and in theory might not even have all response headers if converted to a more optimal representation. If you consider JavaScript modules, they are de-duped based on their request URL in a module map. If the first response for such a URL had , we still wouldn't be making any further requests. The same goes for images, style sheets, and some other resources as I understand it and for some of these changing that would result in compatibility issues (or presumably functional errors in case of module maps). For back-forward in particular it might be worth reading URL There's a worry that an explicit opt-out could end up cargo-culted and make the feature unusable.
NAME that makes sense, I agree the current wording is too strong. How about changing apparent to or easily controllable by the user, it is strongly encouraged to honour basic control mechanisms like Cache-Control: no-store, as they indicate the resource's intent regarding caching. to: apparent to or easily controllable by the user, it is strongly encouraged to define its operation with respect to HTTP cache directives, so as not to surprise authors who expect caching semantics to be honoured. For example, while it might be reasonable to define an application cache "above" HTTP that allows a response containing Cache-Control: no-store to be reused for requests that are directly related to the request that fetched it (such as those created during the same page load), it would likely be surprising and confusing to users and authors if it were allowed to be reused for requests unrelated in any way to the one from which it was obtained.
I think that's good. Some of the caches I mentioned do cross page loads (e.g., images and style sheets). However, I think the statement about those is correct and we should be better about explaining how they fit in and make sense (and perhaps adjust if they don't).
It seems to me that cross-page loads are exactly the type of thing that a sender of no-store is trying to avoid. It is the type of flag sent on highly sensitive or volatile data. Images, stylesheets, etc which have cross-page relevance should not be using it.


and only define the versioning there; leave message version requirements in control data. (no content changes)


This eliminates confusion with the message body protocol element of HTTP/1.1 and other usage of multipart body parts, and should make it easier to describe HTTP/2 and HTTP/3 data frames.
except for multipart body parts or when referring specifically to HTTP/1.1 message body.
See related comment: URL
I believe this is good; but more eyes are needed :-) If we go ahead with that, we may want to call out the new terminolody in one of the "changes from 723x" sections.


Recently I noticed that the host header field is being discussed in . I believe that we should move the definition of the host header to the HTTP/1.1 messaging draft, and discuss about "authority" as a concept in the semantics draft, as the "host" header is specific to HTTP/1.1 (except for handling of broken HTTP/2 clients)?
Hi Kazuho, We discussed this on the editors' call. Host's semantics aren't specific to HTTP/1.1, even if its requirements are different in other protocol versions. That's why we moved it to Semantics; it's not version-specific (and really very few headers should be). Closing; if you feel it needs more discussion please request re-opening and we'll do so.
Thank you for the consideration. While I do understand the argument that the semantics of the header field is not version specific, the use is. I've opened a PR that tries to clarify that.
Thank you for the changes!


by changing DL to a table and tweaking description of HEAD.
"HEAD: the same representation as GET, but without the representation data;" Should that be "payload data"?
No, that's correct, but I will tweak it slightly: HEAD: the same representation as GET, but without transferring the representation data;
Note that the context is a discussion of what representation is included in a 200 response, which is why we are talking about representation data here instead of payload data.


"The 203 response is similar to the Warning code of 214 Transformation Applied (Section 5.5 of [Caching]), which has the advantage of being applicable to responses with any status code." But then we have removed "Warning"...
I think we can just remove this text; if it's important, we can refer to 7234 and mention that it's deprecated.
I say just remove the sentence.


" For example, services that depend on individual user authentication often require a connection to be secured with TLS ("Transport Layer Security", [RFC8446]) prior to exchanging any credentials." This originates from RFC 7235. Nowaday, shouldn't we instead say "require HTTPS"?
I think it should be ... authentication require a secured connection prior to exchanging any credentials (ref target="URL"). and x:ref around the term "secured" (defined in that section).


" Considerations related to message syntax, parsing, and routing are discussed in Section 11 of [Messaging]." Make clear that these are only the HTTP/1.1 considerations. Optionally add links for HTTP/2 and HTTP/3.


"This document defines the semantics of HTTP: its architecture, terminology, the "http" and "https" Uniform Resource Identifier (URI) schemes, core request methods, request header fields, response status codes, response header fields, and content negotiation." replace by just "fields"?
I think it's useful to retain the current text, because those phrases are more likely to be recognised by readers coming to the document.
No real opinion, but it should be rewritten anyway: This document defines the semantics shared by all versions of the Hypertext Transfer Protocol (HTTP), including its architecture, terminology, and core protocol elements, along with the "http" and "https" identifier schemes. It could go on from there to describe the core elements, and maybe the core features as well, but shrug.


initial commit is just moving sections and updating headings; second commit will update some of "the following" comments to refer to the specific fields.
I believe it needs to be under "Proactive Negotiation" , or be a sibling of these...


(this text is present in RFC 7233 as well) "A valid entity-tag can be distinguished from a valid HTTP-date by examining the first two characters for a DQUOTE." Hm, no. If we want to properly handle weak etags, we either need to inspect three characters (actually position 0 and 2) for DQUOTE, or check pos 0 for DQUOTE or pos 1 for "/". If we're not interested in weak etags, checking the first character is sufficient.


"The reason phrases listed here are only recommendations — they can be replaced by local equivalents without affecting the protocol." "URL left out altogether..." ?
(need to check where the fix went)


to be removed ... it was just leftover from the old org. Also, we should call it Request Context Fields.


"If the client has an outstanding request in transit, the client MAY repeat that request on a new connection."
I don't think this needs to be changed (connection is a defined term), but if you can think of some other way to say that the 408 implies partial receipt of the last request (which means the connection gone broke) then go ahead.
Suggestion:
+1


: "A server MUST ignore a Range header field received with a request method other than GET." : "Likewise, if the new method might have some use for partial response semantics (Section 14.2), it ought to document this, too."
I can see why someone might want to use it with SEARCH as well, though they would more likely use a page parameter. I can't think of any other use case.
FWIW, that's exactly how it was used by MS in Exchange SEARCH: We need to decide which of the statements in our spec is correct.
Huh, that's news for me. We could have used that example for Range extensions.
Change requirement to MUST ignore Range when not defined for that method or the method is unrecognized.


Note that I also cleaned up the surrounding paragraph and removed parentheses from around the statement that the response always terminates after the header section.
currently links to "Message Payload", but that is not that helpful in order to find out what fields actually are "payload header fields".
Note. We currently say: "The server SHOULD send the same header fields in response to a HEAD request as it would have sent if the request had been a GET, except that the payload header fields (Section 6.4) MAY be omitted." URL would change this to: "The server SHOULD send the same header fields in response to a HEAD request as it would have sent if the request had been a GET, except that header fields that describe message body encoding or transmission (e.g., Transfer-Encoding) MAY be omitted." (me confused by that)
I should probably just list them all. Content-Length and Transfer-Encoding are the obvious ones, but I would have to go through the spec to be sure there are not more. The reason for this is that servers do not generate the body on HEAD responses, so the fields that are defined while buffering the first 8K of body (when they can still be sent as headers) are not sent on HEAD responses. Maybe we should just say that.


"This directive is NOT a reliable or sufficient mechanism for ensuring privacy." Should be lowercase. Could use .
also in 5.2.2.4


"Additionally, specific HTTP versions can use it to indicate the transfer codings the client is willing to accept in the response." If we phrase it this way, we'd have to say somewhere in Semantics what transfer codings actually are. Or we decide that they are specific to HTTP/1.*, rephrase this, and link to Messaging.


Good point.
For .
URL be good to have tests...
goes back to URL
sent mail: URL
See URL
Proposal: leave weight in ABNF for consistency with other Accept-* fields change second requirement (on recipients) not to rely on "q" being last


Im ok with replacing the 0.9 reference (although having the link here acknowledges where 0.9 came from, right). The idea was to mention 0.9 in the context of RFC 1945 as well as that is an IETF document which actually describes what 0.9 is.
URL out that RFC 1945 defines HTTP/0.9 as well (see URL). Maybe we should add this reference, or replace the existing one.
We do reference 1945 for HTTP/1.0. Revised proposal: just mention that that RFC describes 0.9 as well.