From ae85cf4b6c02ba9c330d436bbee39d211428755d Mon Sep 17 00:00:00 2001 From: Manuel Recena Date: Sat, 5 Mar 2016 17:42:25 +0100 Subject: [PATCH 1/5] Improve checkApiUrlValidity() method to support the private mode in GitHub Enterprise servers --- src/main/java/org/kohsuke/github/GitHub.java | 30 ++++++++++++++++++- .../java/org/kohsuke/github/GitHubTest.java | 7 ++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 77d178800c..14e7b13368 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -31,6 +31,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; +import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.text.ParseException; @@ -482,7 +483,34 @@ void check(String apiUrl) throws IOException { * Otherwise this method throws {@link IOException} to indicate the problem. */ public void checkApiUrlValidity() throws IOException { - retrieve().to("/", GHApiInfo.class).check(apiUrl); + try { + retrieve().to("/", GHApiInfo.class).check(apiUrl); + } catch (IOException ioe) { + if (isPrivateModeEnabled()) { + throw new IOException("GitHub Enterprise server (" + apiUrl + ") with private mode enabled"); + } + throw ioe; + } + } + + /** + * Ensures if a GitHub Enterprise server is configured in private mode. + * + * @return {@code true} if private mode is enabled. If it tries to use this method with GitHub, returns {@code + * false}. + */ + private boolean isPrivateModeEnabled() { + try { + HttpURLConnection connect = getConnector().connect(getApiURL("/")); + if (connect.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED + && connect.getHeaderField("Server") != null + && connect.getHeaderField("Server").equals("GitHub.com")) { + return true; + } + return false; + } catch (IOException e) { + return false; + } } /** diff --git a/src/test/java/org/kohsuke/github/GitHubTest.java b/src/test/java/org/kohsuke/github/GitHubTest.java index 1663d24144..b8ae4ff0df 100644 --- a/src/test/java/org/kohsuke/github/GitHubTest.java +++ b/src/test/java/org/kohsuke/github/GitHubTest.java @@ -124,6 +124,11 @@ public void testGitHubEnterpriseDoesNotHaveRateLimit() throws IOException { @Test public void testGitHubIsApiUrlValid() throws IOException { GitHub github = GitHub.connectAnonymously(); - github.checkApiUrlValidity(); + //GitHub github = GitHub.connectToEnterpriseAnonymously("https://github.mycompany.com/api/v3/"); + try { + github.checkApiUrlValidity(); + } catch (IOException ioe) { + assertTrue(ioe.getMessage().contains("private mode enabled")); + } } } From cd8d9556468475e8ed6108a6499f4cd119a0a899 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 11 Mar 2016 23:06:21 -0800 Subject: [PATCH 2/5] Documenting what one gets --- src/main/java/org/kohsuke/github/GitHub.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 14e7b13368..10bb3ea090 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -502,6 +502,25 @@ public void checkApiUrlValidity() throws IOException { private boolean isPrivateModeEnabled() { try { HttpURLConnection connect = getConnector().connect(getApiURL("/")); + /* + $ curl -i https://github.mycompany.com/api/v3/ + HTTP/1.1 401 Unauthorized + Server: GitHub.com + Date: Sat, 05 Mar 2016 19:45:01 GMT + Content-Type: application/json; charset=utf-8 + Content-Length: 130 + Status: 401 Unauthorized + X-GitHub-Media-Type: github.v3 + X-XSS-Protection: 1; mode=block + X-Frame-Options: deny + Content-Security-Policy: default-src 'none' + Access-Control-Allow-Credentials: true + Access-Control-Expose-Headers: ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval + Access-Control-Allow-Origin: * + X-GitHub-Request-Id: dbc70361-b11d-4131-9a7f-674b8edd0411 + Strict-Transport-Security: max-age=31536000; includeSubdomains; preload + X-Content-Type-Options: nosniff + */ if (connect.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED && connect.getHeaderField("Server") != null && connect.getHeaderField("Server").equals("GitHub.com")) { From 10f55cc54926ab47da73da6d54dc3dd52f397add Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 11 Mar 2016 23:10:41 -0800 Subject: [PATCH 3/5] Checking another header I think it's better to pick a header that's unique to GitHub. --- src/main/java/org/kohsuke/github/GitHub.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index 10bb3ea090..b8673e4533 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -25,6 +25,7 @@ import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY; import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE; +import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED; import java.io.ByteArrayInputStream; import java.io.FileNotFoundException; @@ -501,7 +502,7 @@ public void checkApiUrlValidity() throws IOException { */ private boolean isPrivateModeEnabled() { try { - HttpURLConnection connect = getConnector().connect(getApiURL("/")); + HttpURLConnection uc = getConnector().connect(getApiURL("/")); /* $ curl -i https://github.mycompany.com/api/v3/ HTTP/1.1 401 Unauthorized @@ -521,12 +522,8 @@ private boolean isPrivateModeEnabled() { Strict-Transport-Security: max-age=31536000; includeSubdomains; preload X-Content-Type-Options: nosniff */ - if (connect.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED - && connect.getHeaderField("Server") != null - && connect.getHeaderField("Server").equals("GitHub.com")) { - return true; - } - return false; + return uc.getResponseCode() == HTTP_UNAUTHORIZED + && uc.getHeaderField("X-GitHub-Media-Type") != null; } catch (IOException e) { return false; } From 3b764f9c9081df2a93922603506f5df976394182 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 11 Mar 2016 23:11:22 -0800 Subject: [PATCH 4/5] Don't lose the original problem --- src/main/java/org/kohsuke/github/GitHub.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index b8673e4533..cb94f1076e 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -486,11 +486,11 @@ void check(String apiUrl) throws IOException { public void checkApiUrlValidity() throws IOException { try { retrieve().to("/", GHApiInfo.class).check(apiUrl); - } catch (IOException ioe) { + } catch (IOException e) { if (isPrivateModeEnabled()) { - throw new IOException("GitHub Enterprise server (" + apiUrl + ") with private mode enabled"); + throw (IOException)new IOException("GitHub Enterprise server (" + apiUrl + ") with private mode enabled").initCause(e); } - throw ioe; + throw e; } } From 1954a9f3f8d998ad6a349c044960a33cd24bfd9a Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Fri, 11 Mar 2016 23:12:50 -0800 Subject: [PATCH 5/5] This isn't just about API URL but it also checks the valid credential --- src/main/java/org/kohsuke/github/GitHub.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/kohsuke/github/GitHub.java b/src/main/java/org/kohsuke/github/GitHub.java index cb94f1076e..7aa928e782 100644 --- a/src/main/java/org/kohsuke/github/GitHub.java +++ b/src/main/java/org/kohsuke/github/GitHub.java @@ -477,7 +477,10 @@ void check(String apiUrl) throws IOException { } /** - * Ensures that the API URL is valid. + * Tests the connection. + * + *

+ * Verify that the API URL and credentials are valid to access this GitHub. * *

* This method returns normally if the endpoint is reachable and verified to be GitHub API URL.