From c6de625624e6265e8162db713652f8d57175fcd7 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 4 May 2026 14:10:00 +0100 Subject: [PATCH 1/3] ci: use the new `initial-redirect:none` repo poxygit now supports a "specification" within the URI that can provide additional details about the mock/debugging connection. The `:none` suffix on the redirect request indicates that the proxy should send a 0 byte response body. --- ci/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/test.sh b/ci/test.sh index 6e435655e..19d466a65 100755 --- a/ci/test.sh +++ b/ci/test.sh @@ -299,7 +299,7 @@ if should_run "ONLINE_TESTS"; then echo "## Running networking (online) tests" echo "##############################################################################" - export GITTEST_REMOTE_REDIRECT_INITIAL="http://localhost:9000/initial-redirect/libgit2/TestGitRepository" + export GITTEST_REMOTE_REDIRECT_INITIAL="http://localhost:9000/initial-redirect:none/libgit2/TestGitRepository" export GITTEST_REMOTE_REDIRECT_SUBSEQUENT="http://localhost:9000/subsequent-redirect/libgit2/TestGitRepository" export GITTEST_REMOTE_SPEED_SLOW="http://localhost:9000/speed:9600/test.git" export GITTEST_REMOTE_SPEED_TIMESOUT="http://localhost:9000/speed:0.5/test.git" From 293aa397855ab38db729fea5dc6b67c7c8651b57 Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 4 May 2026 14:08:06 +0100 Subject: [PATCH 2/3] httpclient: update complete_response_body explanation --- src/libgit2/transports/httpclient.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/libgit2/transports/httpclient.c b/src/libgit2/transports/httpclient.c index e27d40b5f..c27d005e1 100644 --- a/src/libgit2/transports/httpclient.c +++ b/src/libgit2/transports/httpclient.c @@ -1243,13 +1243,16 @@ GIT_INLINE(int) client_read_and_parse(git_http_client *client) } /* - * See if we've consumed the entire response body. If the client was - * reading the body but did not consume it entirely, it's possible that - * they knew that the stream had finished (in a git response, seeing a - * final flush) and stopped reading. But if the response was chunked, - * we may have not consumed the final chunk marker. Consume it to - * ensure that we don't have it waiting in our socket. If there's - * more than just a chunk marker, close the connection. + * Try to consume any remaining response body. The client may have + * decided that it did not need to consume the entire response body. + * For example, the client saw a redirect in the header and ignored + * the body. Or the client saw a particular sequence (like a final + * flush in a git response) and stopped reading (but there were + * additional response bytes, perhaps because the response was chunked). + * Do one more read to try to clear this out; this takes care of small + * remainders, like a chunk response or a small redirect message. If + * there is too much data, we'll just leave it and close the + * connection. */ static void complete_response_body(git_http_client *client) { From 242d66e931de2189e910639d26df5a8373e333fe Mon Sep 17 00:00:00 2001 From: Edward Thomson Date: Mon, 4 May 2026 14:01:25 +0100 Subject: [PATCH 3/3] httpclient: stop if there's no content length When we were done reading headers, we checked if we needed to read a body, or if we were done. The body check was done by looking at the transfer encoding type and the content type. If we were chunked, then we know we have a body (it may be a zero byte body, but we would need to read the chunk length to know this). But looking at the content _type_ was erroneous; we should have been looking at the content _length_. The effect of this is that when a server sends a zero byte response with a content _type_, we try to go read the body, which does not exist. We will hang waiting for the body that the server will never send. Correct this typo. Now we will try to read the body if there was a content _length_ specified, or if the transfer encoding is chunked. --- src/libgit2/transports/httpclient.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libgit2/transports/httpclient.c b/src/libgit2/transports/httpclient.c index c27d005e1..86bae396e 100644 --- a/src/libgit2/transports/httpclient.c +++ b/src/libgit2/transports/httpclient.c @@ -379,7 +379,7 @@ static int on_headers_complete(git_http_parser *parser) ctx->response->resend_credentials = resend_needed(ctx->client, ctx->response); - if (ctx->response->content_type || ctx->response->chunked) + if (ctx->response->content_length || ctx->response->chunked) ctx->client->state = READING_BODY; else ctx->client->state = DONE;