equal
deleted
inserted
replaced
281 .thenCompose(Function.identity()); |
281 .thenCompose(Function.identity()); |
282 } |
282 } |
283 return cf; |
283 return cf; |
284 } |
284 } |
285 |
285 |
|
286 private static boolean retryPostValue() { |
|
287 String s = Utils.getNetProperty("jdk.httpclient.enableAllMethodRetry"); |
|
288 if (s == "" || "true".equals(s)) |
|
289 return true; |
|
290 return false; |
|
291 } |
|
292 |
|
293 /** True if ALL ( even non-idempotent ) requests can be automatic retried. */ |
|
294 private static final boolean RETRY_ALWAYS = retryPostValue(); |
|
295 |
|
296 /** Returns true is given request has an idempotent method. */ |
|
297 private static boolean isIdempotentRequest(HttpRequest request) { |
|
298 String method = request.method(); |
|
299 switch (method) { |
|
300 case "GET" : |
|
301 case "HEAD" : |
|
302 return true; |
|
303 default : |
|
304 return false; |
|
305 } |
|
306 } |
|
307 |
|
308 /** Returns true if the given request can be automatically retried. */ |
|
309 private static boolean canRetryRequest(HttpRequest request) { |
|
310 if (isIdempotentRequest(request)) |
|
311 return true; |
|
312 if (RETRY_ALWAYS) |
|
313 return true; |
|
314 return false; |
|
315 } |
|
316 |
286 /** |
317 /** |
287 * Takes a Throwable and returns a suitable CompletableFuture that is |
318 * Takes a Throwable and returns a suitable CompletableFuture that is |
288 * completed exceptionally, or null. |
319 * completed exceptionally, or null. |
289 */ |
320 */ |
290 private CompletableFuture<Response> getExceptionalCF(Throwable t) { |
321 private CompletableFuture<Response> getExceptionalCF(Throwable t) { |
294 } |
325 } |
295 } |
326 } |
296 if (cancelled && t instanceof IOException) { |
327 if (cancelled && t instanceof IOException) { |
297 t = new HttpTimeoutException("request timed out"); |
328 t = new HttpTimeoutException("request timed out"); |
298 } else if (t instanceof ConnectionExpiredException) { |
329 } else if (t instanceof ConnectionExpiredException) { |
|
330 Throwable cause = t; |
|
331 if (t.getCause() != null) { |
|
332 cause = t.getCause(); // unwrap the ConnectionExpiredException |
|
333 } |
|
334 |
|
335 if (!canRetryRequest(currentreq)) { |
|
336 return failedFuture(cause); // fails with original cause |
|
337 } |
|
338 |
299 // allow the retry mechanism to do its work |
339 // allow the retry mechanism to do its work |
300 // ####: method (GET,HEAD, not POST?), no bytes written or read ( differentiate? ) |
340 retryCause = cause; |
301 if (t.getCause() != null) retryCause = t.getCause(); |
|
302 if (!expiredOnce) { |
341 if (!expiredOnce) { |
303 DEBUG_LOGGER.log(Level.DEBUG, |
342 DEBUG_LOGGER.log(Level.DEBUG, |
304 "ConnectionExpiredException (async): retrying...", |
343 "ConnectionExpiredException (async): retrying...", |
305 t); |
344 t); |
306 expiredOnce = true; |
345 expiredOnce = true; |