Skip to content

Commit 8ef6f0f

Browse files
http: add support for HTTP 429 rate limit retries
Add retry logic for HTTP 429 (Too Many Requests) responses to handle server-side rate limiting gracefully. When Git's HTTP client receives a 429 response, it can now automatically retry the request after an appropriate delay, respecting the server's rate limits. The implementation supports the RFC-compliant Retry-After header in both delay-seconds (integer) and HTTP-date (RFC 2822) formats. If a past date is provided, Git retries immediately without waiting. Retry behavior is controlled by three new configuration options (http.maxRetries, http.retryAfter, and http.maxRetryTime) which are documented in git-config(1). The retry logic implements a fail-fast approach: if any delay (whether from server header or configuration) exceeds maxRetryTime, Git fails immediately with a clear error message rather than capping the delay. This provides better visibility into rate limiting issues. The implementation includes extensive test coverage for basic retry behavior, Retry-After header formats (integer and HTTP-date), configuration combinations, maxRetryTime limits, invalid header handling, environment variable overrides, and edge cases. Signed-off-by: Vaidas Pilkauskas <vaidas.pilkauskas@shopify.com>
1 parent ef48cab commit 8ef6f0f

10 files changed

Lines changed: 633 additions & 41 deletions

File tree

Documentation/config/http.adoc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,29 @@ http.keepAliveCount::
315315
unset, curl's default value is used. Can be overridden by the
316316
`GIT_HTTP_KEEPALIVE_COUNT` environment variable.
317317

318+
http.retryAfter::
319+
Default wait time in seconds before retrying when a server returns
320+
HTTP 429 (Too Many Requests) without a Retry-After header.
321+
Defaults to 0 (retry immediately). When a Retry-After header is
322+
present, its value takes precedence over this setting. Can be
323+
overridden by the `GIT_HTTP_RETRY_AFTER` environment variable.
324+
See also `http.maxRetries` and `http.maxRetryTime`.
325+
326+
http.maxRetries::
327+
Maximum number of times to retry after receiving HTTP 429 (Too Many
328+
Requests) responses. Set to 0 (the default) to disable retries.
329+
Can be overridden by the `GIT_HTTP_MAX_RETRIES` environment variable.
330+
See also `http.retryAfter` and `http.maxRetryTime`.
331+
332+
http.maxRetryTime::
333+
Maximum time in seconds to wait for a single retry attempt when
334+
handling HTTP 429 (Too Many Requests) responses. If the server
335+
requests a delay (via Retry-After header) or if `http.retryAfter`
336+
is configured with a value that exceeds this maximum, Git will fail
337+
immediately rather than waiting. Default is 300 seconds (5 minutes).
338+
Can be overridden by the `GIT_HTTP_MAX_RETRY_TIME` environment
339+
variable. See also `http.retryAfter` and `http.maxRetries`.
340+
318341
http.noEPSV::
319342
A boolean which disables using of EPSV ftp command by curl.
320343
This can be helpful with some "poor" ftp servers which don't

git-curl-compat.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@
3737
#define GIT_CURL_NEED_TRANSFER_ENCODING_HEADER
3838
#endif
3939

40+
/**
41+
* CURLINFO_RETRY_AFTER was added in 7.66.0, released in September 2019.
42+
* It allows curl to automatically parse Retry-After headers.
43+
*/
44+
#if LIBCURL_VERSION_NUM >= 0x074200
45+
#define GIT_CURL_HAVE_CURLINFO_RETRY_AFTER 1
46+
#endif
47+
4048
/**
4149
* CURLOPT_PROTOCOLS_STR and CURLOPT_REDIR_PROTOCOLS_STR were added in 7.85.0,
4250
* released in August 2022.

0 commit comments

Comments
 (0)