http: ignore invalid Retry-After times

- Treat negative Retry-After date-based times as 0.

- Treat Retry-After times greater than 6 hours as 6 hours.

Prior to this change Retry-After did not have a limited range and the
server could have set a time greater than 6 hours or a date in the past
that would result in a negative time, either of which may be unexpected
by the user.

The 6 hour limit is purposely not documented so that it can be changed
in the future if necessary.

Closes https://github.com/curl/curl/pull/15833
This commit is contained in:
Jay Satiro 2024-12-26 15:38:39 -05:00
parent 8d1f26b866
commit 6c70ec16c7
4 changed files with 20 additions and 12 deletions

View File

@ -36,6 +36,11 @@ While the HTTP header might contain a fixed date string, the
CURLINFO_RETRY_AFTER(3) always returns the number of seconds to wait -
or zero if there was no header or the header could not be parsed.
This option used to return a negative wait time if the server provided a date
in the past. Since 8.12.0, a negative wait time is returned as zero. In any
case we recommend checking that the wait time is within an acceptable range for
your circumstance.
# DEFAULT
Zero if there was no header.

View File

@ -2901,11 +2901,19 @@ static CURLcode http_header(struct Curl_easy *data,
(void)curlx_strtoofft(v, NULL, 10, &retry_after);
if(!retry_after) {
time_t date = Curl_getdate_capped(v);
if((time_t)-1 != date)
time_t current = time(NULL);
if((time_t)-1 != date && date > current) {
/* convert date to number of seconds into the future */
retry_after = date - time(NULL);
retry_after = date - current;
}
}
data->info.retry_after = retry_after; /* store it */
if(retry_after < 0)
retry_after = 0;
/* limit to 6 hours max. this is not documented so that it can be changed
in the future if necessary. */
if(retry_after > 21600)
retry_after = 21600;
data->info.retry_after = retry_after;
return CURLE_OK;
}
break;

View File

@ -13,9 +13,9 @@ If-Modified-Since
<reply>
<data nocheck="yes">
HTTP/1.1 429 Too Many Requests
Date: Thu, 11 Jul 2019 02:26:59 GMT
Date: Wed, 31 Dec 2036 02:26:59 GMT
Server: test-server/swsclose
Retry-After: Thu, 11 Jul 2024 02:26:59 GMT
Retry-After: Wed, 31 Dec 2036 02:26:59 GMT
</data>
</reply>
@ -42,8 +42,9 @@ Host: %HOSTIP:%HTTPPORT
Accept: */*
</protocol>
# Retry-After time is limited to 6 hours (21600 seconds)
<stdout>
Retry-After 172066
Retry-After 21600
</stdout>
</verify>
</testcase>

View File

@ -49,12 +49,6 @@ CURLcode test(char *URL)
if(res)
goto test_cleanup;
#ifdef LIB1596
/* we get a relative number of seconds, so add the number of seconds
we're at to make it a somewhat stable number. Then remove accuracy. */
retry += time(NULL);
retry /= 10000;
#endif
printf("Retry-After %" CURL_FORMAT_CURL_OFF_T "\n", retry);
test_cleanup: