Class RetryAfterParser

java.lang.Object
com.maybeitssquid.retry.RetryAfterParser
All Implemented Interfaces:
Function<jakarta.servlet.http.HttpServletResponse, Optional<Duration>>

public class RetryAfterParser extends Object implements Function<jakarta.servlet.http.HttpServletResponse, Optional<Duration>>
Parses an HTTP Retry-After header to determine how long to wait before retrying. Parsing of the header is based on a superset of RFC 7231. Anything permitted by that RFC should parse correctly. Minor variations may be allowed, such as fractional seconds, optional day name, single-digit hour/minute/second, optional seconds, extra whitespace before the hour.
  • Field Details

    • LOGGER

      public static final org.slf4j.Logger LOGGER
      Logger for errors during parsing, particularly to diagnose a misbehaving server.
    • RETRY_AFTER_HEADER

      public static final String RETRY_AFTER_HEADER
      The Retry-After header name.
      See Also:
    • MAX_DELAY

      public static final Duration MAX_DELAY
      The longest delay this parser will report. A server that asks for more than can be expressed in milliseconds is clamped to this rather than having the value wrap or be discarded, so the delay still exceeds any limit a caller has configured and the retry is refused rather than allowed.
    • STRICT_SECONDS

      public static final Function<String, Optional<Duration>> STRICT_SECONDS
      Accept Retry-After header that matches only strict RFC 7231 delay-seconds.

      A delay too large to express in milliseconds is clamped to MAX_DELAY rather than wrapped or discarded, so every Duration this parser returns is safe to pass to Duration.toMillis() and still exceeds any sane limit.

    • DECIMAL_SECONDS

      public static final Function<String, Optional<Duration>> DECIMAL_SECONDS
      Accept extended Retry-After header that allows decimal seconds.

      Precision finer than a millisecond is truncated, and an oversized delay is clamped to MAX_DELAY, matching STRICT_SECONDS.

    • IMF_FIXDATE

      public static final Function<String, Optional<ZonedDateTime>> IMF_FIXDATE
      Forgiving parser for a superset of IMF-fixdate using the builtin DateTimeFormatter.RFC_1123_DATE_TIME

      Example: "Thu, 02 Jan 2003 01:23:45 GMT"

    • RFC_850

      public static final Function<String, Optional<ZonedDateTime>> RFC_850
      Forgiving parer for a superset of RFC-850 dates.

      Example: "Thursday, 02-Jan-03 01:23:45 GMT"

    • ASCTIME

      public static final Function<String, Optional<ZonedDateTime>> ASCTIME
      Forgiving parer for a superset of ASCTIME dates.

      Example: "Thu Jan 2 01:23:45 2003"

    • ISO

      public static final Function<String, Optional<ZonedDateTime>> ISO
      Parser for ISO-8601 dates. Any number of fractional second digits from 1 to 9 is accepted, not only whole groups of three.

      Example: "2011-12-03T10:15:30Z" Example: "2011-12-03T10:15:30.1Z" Example: "2011-12-03T10:15:30.123Z" Example: "2011-12-03T10:15:30.123456789Z"

  • Method Details

    • secondsOnly

      public static RetryAfterParser secondsOnly()
      Parser that accepts only Retry-After headers with an integer number of seconds to wait. If the header contains some other value, such as a date, it is ignored.
      Returns:
      Parser that accepts only delay-seconds in the Retry-After header.
    • decimalSeconds

      public static RetryAfterParser decimalSeconds()
      Parser that accepts Retry-After headers with a potentially decimal number of seconds to wait. If the header contains some other value, such as a date, it is ignored.
      Returns:
      Parser that accepts only seconds in the Retry-After header.
    • strict

      public static RetryAfterParser strict(InstantSource clock)
      Parser that accepts only Retry-After headers that meet a reasonably strict interpretation of RFC-9110.
      Parameters:
      clock - the clock to use to compute offsets when the header is a date. Useful for testing.
      Returns:
      Parser for RFC-9110 Retry-After headers.
    • strict

      public static RetryAfterParser strict()
      Parser that accepts only Retry-After headers that meet a reasonably strict interpretation of RFC-9110. Uses system clock to compute offsets when the header is a date.
      Returns:
      Parser for RFC-9110 Retry-After headers.
    • extended

      public static RetryAfterParser extended(InstantSource clock)
      Parser that accepts Retry-After headers that meet a superset of RFC-9110, including headers with a decimal number of seconds delay and ISO-8601 instants.
      Parameters:
      clock - the clock to use to compute offsets when the header is a date. Useful for testing.
      Returns:
      Parser for extended Retry-After headers.
    • extended

      public static RetryAfterParser extended()
      Parser that accepts Retry-After headers that meet a superset of RFC-9110, including headers with a decimal number of seconds delay. Uses system clock to compute offsets when the header is a date.
      Returns:
      Parser for extended Retry-After headers.
    • apply

      public Optional<Duration> apply(jakarta.servlet.http.HttpServletResponse response)
      Parser to recognize the Retry-After formats defined in section 5.6.6 of RFC-9110 and convert the value to a duration. If the header specified a date, the duration is relative to the current time.

      The source of current time defaults to the system clock, but can be overridden by supplying an InstantSource to the constructor.

      Specified by:
      apply in interface Function<jakarta.servlet.http.HttpServletResponse, Optional<Duration>>
      Parameters:
      response - the raw HTTP servlet response
      Returns:
      duration until a retry is allowed