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;
}