Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -141,14 +141,25 @@ long getRetryAfter(Response response, long delay, int executionCount) {
return (long) Math.min(retryDelay, RetryHandlerOption.MAX_DELAY * DELAY_MILLISECONDS);
}

/**
* Return first positive value from the Retry-After header.
* @param retryAfterHeader The value of the Retry-After header. Sometimes it can contain multiple values separated by commas.
* For example: "31,120".
* @return Retry interval in milliseconds
*/
double tryParseTimeHeader(String retryAfterHeader) {
double retryDelay = -1;
try {
retryDelay = Integer.parseInt(retryAfterHeader) * DELAY_MILLISECONDS;
} catch (NumberFormatException e) {
return retryDelay;
String[] values = retryAfterHeader.split(",");
for (String value : values) {
try {
double parsedValue = Double.parseDouble(value.trim());
if (parsedValue > 0) {
return parsedValue * DELAY_MILLISECONDS;
}
} catch (NumberFormatException e) {
// Continue to the next value
}
}
return retryDelay;
return -1;
}

double tryParseDateHeader(String retryAfterHeader) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.microsoft.kiota.http.middleware;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.stream.Stream;

class RetryHandlerTest {

private static final double DELAY_MILLISECONDS = 1000.0;
private static final double DEFAULT_DELAY_MILLISECONDS = -1.0;
private static final double DELTA = 0.01;

private RetryHandler retryHandler;

@BeforeEach
void setUp() {
retryHandler = new RetryHandler();
}

private static Stream<Arguments> retryAfterHeaderValues() {
return Stream.of(
// Single values
Arguments.of("10", 10.0 * DELAY_MILLISECONDS),
Arguments.of("0", DEFAULT_DELAY_MILLISECONDS), // Zero should return default
Arguments.of("-5", DEFAULT_DELAY_MILLISECONDS), // Negative should return default

// Comma-separated values
Arguments.of("31,120", 31.0 * DELAY_MILLISECONDS), // First positive value
Arguments.of("0,45", 45.0 * DELAY_MILLISECONDS), // Skip zero, take next
Arguments.of("-10,25", 25.0 * DELAY_MILLISECONDS), // Skip negative, take next
Arguments.of("0,-5,60", 60.0 * DELAY_MILLISECONDS), // Skip multiple invalid

// Edge cases
Arguments.of("", DEFAULT_DELAY_MILLISECONDS), // Empty string
Arguments.of(" ", DEFAULT_DELAY_MILLISECONDS), // Whitespace only
Arguments.of("abc", DEFAULT_DELAY_MILLISECONDS), // Invalid number
Arguments.of("10,abc,20", 10.0 * DELAY_MILLISECONDS), // Mixed valid/invalid
Arguments.of("abc,20", 20.0 * DELAY_MILLISECONDS), // Invalid first, valid second
Arguments.of("0,0,0", DEFAULT_DELAY_MILLISECONDS), // All zeros
Arguments.of("-1,-2,-3", DEFAULT_DELAY_MILLISECONDS), // All negative

// Whitespace handling
Arguments.of(" 15 ", 15.0 * DELAY_MILLISECONDS), // Whitespace around value
Arguments.of("10, 20", 10.0 * DELAY_MILLISECONDS), // Whitespace after comma
Arguments.of(" 0 , 30 ", 30.0 * DELAY_MILLISECONDS) // Multiple whitespaces
);
}

@ParameterizedTest
@MethodSource("retryAfterHeaderValues")
void testTryParseTimeHeader(String headerValue, double expectedDelay) {
double result = retryHandler.tryParseTimeHeader(headerValue);
assertEquals(
expectedDelay, result, DELTA, "Failed for header value: '" + headerValue + "'");
}
}