From 16d34f3268a6c52c616a40de3d069a49ca1da361 Mon Sep 17 00:00:00 2001 From: Liam Newman Date: Fri, 17 Jan 2020 14:58:01 -0800 Subject: [PATCH] Workaround for #669 - retry with cache overridden This is much more reasonable way to address this issue. When the Requester detects a 404 response with an ETag (only happpens when the server's 304 is bogus and would cause cache corruption), try the query again with new request header that forces the server to not return 304 and return new data instead. Ths solution is transparent to users of this library and autmatically fixes a situation that was causing cache corruption. If GitHub ever fixes the issue and begins providing accurate ETags to their 404 responses, this will result in two calls being made for each 404 response. While that would be unfortunate, it would still be better than the current situation. --- .../java/org/kohsuke/github/Requester.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/main/java/org/kohsuke/github/Requester.java b/src/main/java/org/kohsuke/github/Requester.java index 60ba91148..c61356e6b 100644 --- a/src/main/java/org/kohsuke/github/Requester.java +++ b/src/main/java/org/kohsuke/github/Requester.java @@ -882,6 +882,26 @@ class Requester { // java.net.URLConnection handles 404 exception has FileNotFoundException, don't wrap exception in // HttpException // to preserve backward compatibility + + // WORKAROUND FOR ISSUE #669: + // When caching GitHub doesn't handle "If-Modified-Since" correctly + // In the case that an item didn't exist (returned 404) but now does exist + // Accurate 404 responses from GitHub do not have ETag information (at this time) + // If we see a 404 with an ETag we treat it as corrupt and make new request with + // caching headers overridden to force refresh. + // If we tried this once already, don't try again. + if (Objects.equals(uc.getRequestMethod(), "GET") + && uc.getHeaderField("ETag") != null + && !Objects.equals(uc.getRequestProperty("Cache-Control"), "no-cache") + && timeouts > 0) { + setupConnection(uc.getURL()); + // Setting "Cache-Control" to "no-cache" stops the cache from supplying + // "If-Modified-Since" or "If-None-Match" values. + // This makes GitHub give us current data (not incorrectly cached data) + uc.setRequestProperty("Cache-Control", "no-cache"); + return parse(type, instance, timeouts - 1); + } + throw e; } catch (IOException e) { if (e instanceof SocketTimeoutException && timeouts > 0) {