Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retry-After header, support non-standard formats #556

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

mrienstra
Copy link

@mrienstra mrienstra commented Jul 12, 2023

I encountered a website (powered by https://www.civicplus.com/civicengage/local-government-website-design ) which adds an s suffix, e.g. 30s instead of 30.

While looking into it, I found this thread, which discusses another non-standard format, 1m0s: urllib3/urllib3#1822

This PR adds support for both of these non-standard formats. AKA invalid formats, but given that it's better to correctly parse the value and respect it (vs. ignoring it), seems worth doing.

Decided to pull these changes out into a parseRetryAfter method for readability. Doing so made it easy to get rid of the nested ifs. Before:

    // The `retry-after` header can come in either <seconds> or
    // A specific date to go check.
    let retryAfter = Number(retryAfterRaw) * 1000 + Date.now();
    if (isNaN(retryAfter)) {
      retryAfter = Date.parse(retryAfterRaw);
      if (isNaN(retryAfter)) {
        // handle invalid response in formats `1m30s` or `30s`
        const matches = retryAfterRaw.match(/^(?:(\d+)m)?(\d+)s$/);
        if (matches) {
          retryAfter =
            (Number(matches[1] || 0) * 60 + Number(matches[2])) * 1000 +
            Date.now();
        } else {
          return false;
        }
      }
    }

After:

  // The `retry-after` header can come in either <seconds> or
  // A specific date to go check.
  private parseRetryAfter(retryAfterRaw: string): number {
    let retryAfter = Number(retryAfterRaw) * 1000 + Date.now();
    if (!isNaN(retryAfter)) return retryAfter;

    retryAfter = Date.parse(retryAfterRaw);
    if (!isNaN(retryAfter)) return retryAfter;

    // handle invalid response in formats `1m30s` or `30s`
    const matches = retryAfterRaw.match(/^(?:(\d+)m)?(\d+)s$/);
    if (!matches) return NaN;
    return (
      (Number(matches[1] || 0) * 60 + Number(matches[2])) * 1000 + Date.now()
    );
  }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant