-
Notifications
You must be signed in to change notification settings - Fork 203
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
http deadlock with stream FIN choices #1972
Comments
This isn't really a spec issue, as this 0.9 HTTP design we have had for interop is not explicitly written anywhere. It has been a defacto requirement since the interop 2 or 3 to FIN your HTTP requests. |
I'm referring to HTTP/3, although it came up in a 0.9 interop. I don't believe there is any requirement in the draft for clients to FIN their requests in a timely fashion. |
HTTP/2 doesn't require a client FIN before the server will process the request, but you do need one to complete the stream state machine. I think HQ/H3 should be the same. |
I agree with @nibanks. HTTP/0.9 has two ways of terminating a request: CRLF and a FIN. HTTP/1 introduced the concept of request body along with a It is not the case with H2, where END_STREAM is the only way to terminate a request. I'd assume that that is the same with H3. |
It seems quite reasonable for servers to wait for the FIN before sending
the response. As such it seems like requiring the client FIN the request to
avoid deadlock makes sense to me.
…On Tue, Nov 6, 2018 at 1:20 AM, Kazuho Oku ***@***.***> wrote:
I agree with @nibanks <https://github.com/nibanks>.
HTTP/0.9 has two ways of terminating a request: CRLF and a FIN. HTTP/1
introduced the concept of request body along with a content-length
request header field that allows a server to detect the end of the request
*without* using FIN.
It is not the case with H2, where END_STREAM is the only way to terminate
a request. I'd assume that that is the same with H3.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#1972 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ASp6ymtvyKrIGgQV76RCqI8uVeoFAbuAks5usVRPgaJpZM4YP8rZ>
.
|
Forcing client to FIN doesn't work because of things like CONNECT. Section 3.1.2 of HTTP/QUIC says:
|
Let's not take this discussion too far. All we are talking about is the simple HTTP 0.9 interop protocol we are currently using. We aren't talking HQ/H3. There is nothing but GET and a response body for the current interop. The (unofficial) requirements throughout interop have always been to FIN the request. |
OK that makes sense. As you point out in the 2nd comment @nibanks this isn't really a spec issue, this was a subtlety I missed when skimming. As someone that doesn't do interop, raising issues specific to it (and not the core documents) is awfully confusing. Especially so in future when search engine crawlers bring up old discussions as new implementers jump on board to build HTTP/QUIC software. |
@nibanks Martin D. says it is concerning H3 in a comment in the above and he is OP. |
Ok. Then I think we shouldn't be conflating the two issues of HTTP 0.9 interoperability issues and HQ/H3 design. I'm perfectly fine dedicating the rest of this issue to HQ/H3. For interop, the client FINs the 0.9 request. |
Re HQ, I think we have a clear definition. Section 5.1 states that:
I would interpret this statement that it is OK to use FIN as the way to determine the end of a HTTP request. FWIW, this follows what we have had for H2 in RFC 7540 section 8.1. Re CONNECT case that @LPardue points out, my understanding is that is considered either as an exception or that CONNECT elicits an early response. |
@martinduke filed this issue after discussing with me; while he encountered it with HTTP/0.9 in the interop, the issue applies to HQ as well. What the draft currently says is:
There's no normative language, but there's an expectation that the closure will happen at the end of the request. CONNECT is different, as noted, and (if you support CONNECT, at the very least), you have to look at the request to determine whether to expect it to be closed. In the opposite direction, we say:
While this text is targeted at streams being reset or FIN'd before the request finishes, this could reasonably be interpreted/expanded to say that servers also cannot rely upon the FIN for finding the end of the request. I suspect that you need to process a complete request regardless of whether the stream has closed or not. |
I apologize for giving the impression that I care about 0.9 at all with respect to the draft. As @MikeBishop says, the issue is filed about HTTP/3. @MikeBishop Can you file a PR for whatever changes you think are needed? |
@RyanatGoogle points out that Content-Length isn't mandatory, and when absent, end-of-stream is the only way to identify the end of the body (unless there are trailers). So perhaps we need to be having a more granular conversation here: You have to process headers (and discover whether you're expecting a body) without waiting for the body to arrive. If no body is expected, process the request. If you expect a body and the length is given, read that many bytes. If you expect a body of unknown size, then and only then do you use end-of-stream as a signal. |
Why shouldn't HTTP/3 behave the same way with regard to EOS as HTTP/2 and HTTP/1.x do? |
@dtikhonov Because this is an opportunity to improve the status quo, like we did for TLS 1.3. Since implementors need to at least look at their EOS handling when transitioning from h2 to h3, now would be a good time to clarify the expected behavior. |
While I agree that clarifying what endpoints would do is a good thing, I am not sure if we need to diverge from the model we have in HTTP/2. In HTTP/2, end of a message was EOS, with the only exception being the At the same time, we have allowed the endpoints to start processing parts of the message as they arrive (e.g., early response, progressive rendering of responses). I do not see a reason to change the model in HTTP/3, and therefore my preference goes to retaining the same model in order to reduce the differences between different HTTP versions as well as maximizing the chance to reuse extensions. |
Ah, I got confused between http-core issue 22 and this one, apologies. I just had an opinion on clarifying that closing one half of a stream does not imply closing both sides. I agree that EOS should be the end of a message. |
I agree with @kazuho and @dtikhonov I don't see a good reason to diverge from HTTP/2's model here where end of stream ends the message (and "A request or response is also malformed if the value of a content-length header field does not equal the sum of the DATA frame payload lengths that form the body".) |
In part because in HTTP/2 end-of-stream wasn't a separate thing -- it was a flag on the final header block or DATA frame. You couldn't end a stream elsewhere (though the workaround was a zero-length DATA frame with END_STREAM set). In a more abstract sense, there are HTTP messages which aren't sent atomically -- they develop over time, and have to be handled in a streaming fashion. These might be streamed responses -- or requests, for a POST or a strained protocol adaptation. CONNECT fits into this category, since the "message body" and the "response body" are essentially infinite, and in HTTP/1.1 it was unique in being totally unframed. In HTTP/2, though, pseudo-chunked messages work exactly the same way. To frame it differently, I don't have a problem with saying that EOS is the end of the message; I have a problem with the implication that you can wait for the entire message to arrive before you begin processing it. That's the original incompatible bug that started this issue. |
Is it? The first sentence in this thread reads:
Plus, it really depends on the type of the request? For example, if one is to calculate MD5 sum of the request body and return it as response body (something we did during last interop), one must wait for FIN. An echo-type service (another interop example) must process request body immediately (echo it back) and does not have to wait for FIN. |
On Wed, Nov 14, 2018 at 6:50 PM, Dmitri Tikhonov ***@***.***> wrote:
[...] I have a problem with the implication that you can wait for the
entire message to arrive before you begin processing it. *That's* the
original incompatible bug that started this issue.
Is it? The first sentence in this thread reads:
During interop, I couldn't interop with winquic because I never FIN my
request stream, and winquic doesn't serve the response until the request
FINs.
From the subsequent discussion the request did not have a content-length,
there would be no way for the request to be complete without a FIN and as
such, I would argue, a server would be perfectly well behaved to wait until
the FIN arrives before it processed the request. Mike, would you agree with
this?
|
During interop, I couldn't interop with winquic because I never FIN my request stream, and winquic doesn't serve the response until the request FINs.
My conversation with @MikeBishop suggests that both of us are behaving legally, which is a problem. We should either force clients to FIN (allowing servers to wait for it) or not (not). I don't particularly care which.
The text was updated successfully, but these errors were encountered: