Skip to content

Commit fab66c0

Browse files
authored
Merge pull request #2007 from alexzayats/patch-retry-handler
Patch RetryHandler.tryParseTimeHeader to support comma separated values returned by the server
2 parents 99ed981 + 96dfb7a commit fab66c0

File tree

2 files changed

+78
-6
lines changed

2 files changed

+78
-6
lines changed

components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/RetryHandler.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,14 +141,25 @@ long getRetryAfter(Response response, long delay, int executionCount) {
141141
return (long) Math.min(retryDelay, RetryHandlerOption.MAX_DELAY * DELAY_MILLISECONDS);
142142
}
143143

144+
/**
145+
* Return first positive value from the Retry-After header.
146+
* @param retryAfterHeader The value of the Retry-After header. Sometimes it can contain multiple values separated by commas.
147+
* For example: "31,120".
148+
* @return Retry interval in milliseconds
149+
*/
144150
double tryParseTimeHeader(String retryAfterHeader) {
145-
double retryDelay = -1;
146-
try {
147-
retryDelay = Integer.parseInt(retryAfterHeader) * DELAY_MILLISECONDS;
148-
} catch (NumberFormatException e) {
149-
return retryDelay;
151+
String[] values = retryAfterHeader.split(",");
152+
for (String value : values) {
153+
try {
154+
double parsedValue = Double.parseDouble(value.trim());
155+
if (parsedValue > 0) {
156+
return parsedValue * DELAY_MILLISECONDS;
157+
}
158+
} catch (NumberFormatException e) {
159+
// Continue to the next value
160+
}
150161
}
151-
return retryDelay;
162+
return -1;
152163
}
153164

154165
double tryParseDateHeader(String retryAfterHeader) {
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.microsoft.kiota.http.middleware;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
5+
import org.junit.jupiter.api.BeforeEach;
6+
import org.junit.jupiter.params.ParameterizedTest;
7+
import org.junit.jupiter.params.provider.Arguments;
8+
import org.junit.jupiter.params.provider.MethodSource;
9+
10+
import java.util.stream.Stream;
11+
12+
class RetryHandlerTest {
13+
14+
private static final double DELAY_MILLISECONDS = 1000.0;
15+
private static final double DEFAULT_DELAY_MILLISECONDS = -1.0;
16+
private static final double DELTA = 0.01;
17+
18+
private RetryHandler retryHandler;
19+
20+
@BeforeEach
21+
void setUp() {
22+
retryHandler = new RetryHandler();
23+
}
24+
25+
private static Stream<Arguments> retryAfterHeaderValues() {
26+
return Stream.of(
27+
// Single values
28+
Arguments.of("10", 10.0 * DELAY_MILLISECONDS),
29+
Arguments.of("0", DEFAULT_DELAY_MILLISECONDS), // Zero should return default
30+
Arguments.of("-5", DEFAULT_DELAY_MILLISECONDS), // Negative should return default
31+
32+
// Comma-separated values
33+
Arguments.of("31,120", 31.0 * DELAY_MILLISECONDS), // First positive value
34+
Arguments.of("0,45", 45.0 * DELAY_MILLISECONDS), // Skip zero, take next
35+
Arguments.of("-10,25", 25.0 * DELAY_MILLISECONDS), // Skip negative, take next
36+
Arguments.of("0,-5,60", 60.0 * DELAY_MILLISECONDS), // Skip multiple invalid
37+
38+
// Edge cases
39+
Arguments.of("", DEFAULT_DELAY_MILLISECONDS), // Empty string
40+
Arguments.of(" ", DEFAULT_DELAY_MILLISECONDS), // Whitespace only
41+
Arguments.of("abc", DEFAULT_DELAY_MILLISECONDS), // Invalid number
42+
Arguments.of("10,abc,20", 10.0 * DELAY_MILLISECONDS), // Mixed valid/invalid
43+
Arguments.of("abc,20", 20.0 * DELAY_MILLISECONDS), // Invalid first, valid second
44+
Arguments.of("0,0,0", DEFAULT_DELAY_MILLISECONDS), // All zeros
45+
Arguments.of("-1,-2,-3", DEFAULT_DELAY_MILLISECONDS), // All negative
46+
47+
// Whitespace handling
48+
Arguments.of(" 15 ", 15.0 * DELAY_MILLISECONDS), // Whitespace around value
49+
Arguments.of("10, 20", 10.0 * DELAY_MILLISECONDS), // Whitespace after comma
50+
Arguments.of(" 0 , 30 ", 30.0 * DELAY_MILLISECONDS) // Multiple whitespaces
51+
);
52+
}
53+
54+
@ParameterizedTest
55+
@MethodSource("retryAfterHeaderValues")
56+
void testTryParseTimeHeader(String headerValue, double expectedDelay) {
57+
double result = retryHandler.tryParseTimeHeader(headerValue);
58+
assertEquals(
59+
expectedDelay, result, DELTA, "Failed for header value: '" + headerValue + "'");
60+
}
61+
}

0 commit comments

Comments
 (0)