[FFmpeg-devel] [PATCH v2 4/9] avformat/http: Add support for Retry-After header
Martin Storsjö
martin at martin.st
Wed Apr 24 14:06:32 EEST 2024
On Mon, 22 Apr 2024, Derek Buitenhuis wrote:
> 429 and 503 codes can, and often do (e.g. all Google Cloud
> Storage URLs can), return a Retry-After header with the error,
> indicating how long to wait, in seconds, before retrying again.
> If it is not respected by, for example, using our default backoff
> stratetgy instead, chances of success are very unlikely.
>
> This adds an AVOption to respect that header.
>
> Signed-off-by: Derek Buitenhuis <derek.buitenhuis at gmail.com>
> ---
> libavformat/http.c | 12 ++++++++++++
> libavformat/version.h | 2 +-
> 2 files changed, 13 insertions(+), 1 deletion(-)
Is this feature standardized in a RFC, or is it some other spec somewhere?
I think it would be nice with a link to a spec in the commit message here.
>
> diff --git a/libavformat/http.c b/libavformat/http.c
> index e7603037f4..5ed481b63a 100644
> --- a/libavformat/http.c
> +++ b/libavformat/http.c
> @@ -138,6 +138,8 @@ typedef struct HTTPContext {
> char *new_location;
> AVDictionary *redirect_cache;
> uint64_t filesize_from_content_range;
> + int respect_retry_after;
> + unsigned int retry_after;
> } HTTPContext;
>
> #define OFFSET(x) offsetof(HTTPContext, x)
> @@ -176,6 +178,7 @@ static const AVOption options[] = {
> { "reconnect_on_http_error", "list of http status codes to reconnect on", OFFSET(reconnect_on_http_error), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, D },
> { "reconnect_streamed", "auto reconnect streamed / non seekable streams", OFFSET(reconnect_streamed), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, D },
> { "reconnect_delay_max", "max reconnect delay in seconds after which to give up", OFFSET(reconnect_delay_max), AV_OPT_TYPE_INT, { .i64 = 120 }, 0, UINT_MAX/1000/1000, D },
> + { "respect_retry_after", "respect the Retry-After header when retrying connections", OFFSET(respect_retry_after), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, D },
> { "listen", "listen on HTTP", OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, D | E },
> { "resource", "The resource requested by a client", OFFSET(resource), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, E },
> { "reply_code", "The http status code to return to a client", OFFSET(reply_code), AV_OPT_TYPE_INT, { .i64 = 200}, INT_MIN, 599, E},
> @@ -386,6 +389,13 @@ redo:
> reconnect_delay > s->reconnect_delay_max)
> goto fail;
>
> + if (s->respect_retry_after && s->retry_after > 0) {
> + reconnect_delay = s->retry_after;
It'd be nice with a comment to clarify the units of both values here,
which apparently both happen to be integer seconds?
> + if (reconnect_delay > s->reconnect_delay_max)
> + goto fail;
> + s->retry_after = 0;
> + }
> +
> av_log(h, AV_LOG_WARNING, "Will reconnect at %"PRIu64" in %d second(s).\n", off, reconnect_delay);
> ret = ff_network_sleep_interruptible(1000U * 1000 * reconnect_delay, &h->interrupt_callback);
> if (ret != AVERROR(ETIMEDOUT))
> @@ -1231,6 +1241,8 @@ static int process_line(URLContext *h, char *line, int line_count, int *parsed_h
> parse_expires(s, p);
> } else if (!av_strcasecmp(tag, "Cache-Control")) {
> parse_cache_control(s, p);
> + } else if (!av_strcasecmp(tag, "Retry-After")) {
> + s->retry_after = strtoul(p, NULL, 10);
Can you add a comment here, to clarify what unit the value is expressed
in?
// Martin
More information about the ffmpeg-devel
mailing list