Skip to content

Conversation

xemul
Copy link
Contributor

@xemul xemul commented May 27, 2025

There's a test that highlights an issue in the client's behavior when a socket is closed before all request data is fully read. When this happens, the subsequent request shouldn't receive leftover data from the previous response and fail. For content-length replies this case is handled by client and the test passes. For chunked-encoded bodies, the problem is yet to be fixed.

This test extension is intended solely to demonstrate the problem and does not include a fix. The resolution will be addressed in a follow-up PR.

ref #2767
ref #2768

@xemul xemul requested review from kreuzerkrieg and nyh May 27, 2025 11:41
xemul added 3 commits May 27, 2025 15:03
This is to make next patching a bit simpler

Signed-off-by: Pavel Emelyanov <[email protected]>
When closing server-side connection it may happen that client had
already closed its end and there's nothing to flush into. Neither
there's anything that can be done about it.

Ignoring exception here is safe, all the test wants to check is done on
the client side, server just supplies the reply at its best.

refs: 303d0cb

Signed-off-by: Pavel Emelyanov <[email protected]>
Extend the test with partially-read body to verify the same for
chunked-encoded replies. For now the check fails, because client only
tracks under-read bodies for content-length replies. This is to be fixed
on top.

Signed-off-by: Pavel Emelyanov <[email protected]>
@xemul xemul force-pushed the br-http-client-partial-chunked-body-read-test branch from 4f4da63 to dc1270b Compare May 27, 2025 12:03
@xemul
Copy link
Contributor Author

xemul commented May 27, 2025

upd:

  • ignore server-side exception on socket closing

}
}
out.close().get();
out.close().handle_exception([](auto ex){}).get();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how come after just splitting test to function and the test close() started to throw? Am I missing something?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or it is "test/http: Extend test for improper client handling of aborted requests" would introduce exception throwing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may happen that server "survives" up until the very last flush. Then, since this last flush schedules a batch flush, the exception is set and delivered only on close()

@nyh
Copy link
Contributor

nyh commented May 27, 2025

ref #2767 ref #2768

To reduce the suspense for readers, it's nice to add a few words on how each issue relates to this PR. It also doesn't need to be a separate line - the "ref #..." can appear inline in the middle of a paragraph where you are describing the bug your testing.

Copy link
Contributor

@nyh nyh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's great that you are writing a test to rerproduce a bug (#2768), but I don't think it's a good idea to have tests that enshrine incorrect behavior. I think the test should check the correct behavior, and fail. Ideally we should be able able to mark this test "xfail" ("expected failure") as we can do in pytest - but I don't know how. Another ugly option is just to #if 0 the test out :-(

} else {
// FIXME chunked encoded bodies are not yet checked by client to be
// under-read, so 2nd request will receive the tail of the 1st response
BOOST_REQUIRE_THROW(make_request.get(), httpd::response_parsing_exception);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like to have tests which enshrine wrong behavior. I'd much rather have a test that should pass, and for now we know fails (i.e., "xfail" in pytest lingo). I don't know how to do this in unit tests.
But it still doesn't mean we can have a test which insists that a known bug can't be fixed...

[&content_length](const http::reply& resp, input_stream<char>&& in) {
content_length = resp.content_length;
[&content_length, chunked](const http::reply& resp, input_stream<char>&& in) {
content_length = chunked ? 128_KiB : resp.content_length;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does this 128KB come from? Response chunks have a length written by the server - the client shouldn't guess them. I see below that your server indeed returns the entire response as one chunk - and writes the chunk size in the beginning of the chunk.

auto ss = lcf.get_server_socket();
auto server = ss.accept().then(make_response);
if (size > 128_KiB) {
if (size > 128_KiB && !chunked) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't understand this line

@xemul
Copy link
Contributor Author

xemul commented Oct 21, 2025

Closing in favor of #3063

@xemul xemul closed this Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants