AZ_INLINE AZ_NODISCARD az_result _az_http_policy_retry_get_retry_after()

in sdk/src/azure/core/az_http_policy_retry.c [95:151]


AZ_INLINE AZ_NODISCARD az_result _az_http_policy_retry_get_retry_after(
    az_http_response* ref_response,
    bool* should_retry,
    int32_t* retry_after_msec)
{
  az_http_response_status_line status_line = { 0 };
  _az_RETURN_IF_FAILED(az_http_response_get_status_line(ref_response, &status_line));

  if (!_az_http_policy_retry_should_retry_http_response_code(status_line.status_code))
  {
    *should_retry = false;
    *retry_after_msec = -1;
    return AZ_OK;
  }

  *should_retry = true;

  // Try to get the value of retry-after header, if there's one.
  az_span header_name = { 0 };
  az_span header_value = { 0 };
  while (az_result_succeeded(
      az_http_response_get_next_header(ref_response, &header_name, &header_value)))
  {
    if (az_span_is_content_equal_ignoring_case(header_name, AZ_SPAN_FROM_STR("retry-after-ms"))
        || az_span_is_content_equal_ignoring_case(
            header_name, AZ_SPAN_FROM_STR("x-ms-retry-after-ms")))
    {
      // The value is in milliseconds.
      int32_t const msec = _az_uint32_span_to_int32(header_value);
      if (msec >= 0) // int32_t max == ~24 days
      {
        *retry_after_msec = msec;
        return AZ_OK;
      }
    }
    else if (az_span_is_content_equal_ignoring_case(header_name, AZ_SPAN_FROM_STR("Retry-After")))
    {
      // The value is either seconds or date.
      int32_t const seconds = _az_uint32_span_to_int32(header_value);
      if (seconds >= 0) // int32_t max == ~68 years
      {
        *retry_after_msec = (seconds <= (INT32_MAX / _az_TIME_MILLISECONDS_PER_SECOND))
            ? seconds * _az_TIME_MILLISECONDS_PER_SECOND
            : INT32_MAX;

        return AZ_OK;
      }

      // TODO: Other possible value is HTTP Date. For that, we'll need to parse date, get
      // current date, subtract one from another, get seconds. And the device should have a
      // sense of calendar clock.
    }
  }

  *retry_after_msec = -1;
  return AZ_OK;
}