SLIDER-782 Failed attempt to integrate with the AmWebClient logic for handling redirects across http/https boundary. That code only works for GET operations.
Project: http://git-wip-us.apache.org/repos/asf/incubator-slider/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-slider/commit/6c038b41 Tree: http://git-wip-us.apache.org/repos/asf/incubator-slider/tree/6c038b41 Diff: http://git-wip-us.apache.org/repos/asf/incubator-slider/diff/6c038b41 Branch: refs/heads/develop Commit: 6c038b4132fe8bfdca493d3ef9158bfd838db9db Parents: 73e1639 Author: Steve Loughran <[email protected]> Authored: Fri Jan 23 12:46:34 2015 +0000 Committer: Steve Loughran <[email protected]> Committed: Fri Jan 23 12:48:16 2015 +0000 ---------------------------------------------------------------------- .../core/restclient/UgiJerseyBinding.java | 12 +++- .../restclient/UrlConnectionOperations.java | 69 ++++++++++++++++++-- 2 files changed, 73 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/6c038b41/slider-core/src/main/java/org/apache/slider/core/restclient/UgiJerseyBinding.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/core/restclient/UgiJerseyBinding.java b/slider-core/src/main/java/org/apache/slider/core/restclient/UgiJerseyBinding.java index 76407c6..10ce1ce 100644 --- a/slider-core/src/main/java/org/apache/slider/core/restclient/UgiJerseyBinding.java +++ b/slider-core/src/main/java/org/apache/slider/core/restclient/UgiJerseyBinding.java @@ -33,6 +33,7 @@ import org.apache.hadoop.yarn.webapp.NotFoundException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; @@ -74,7 +75,7 @@ public class UgiJerseyBinding implements /** * Get a URL connection. - * @param url + * @param url URL to connect to * @return the connection * @throws IOException any problem. {@link AuthenticationException} * errors are wrapped @@ -82,6 +83,10 @@ public class UgiJerseyBinding implements @Override public HttpURLConnection getHttpURLConnection(URL url) throws IOException { try { + // open a connection handling status codes and so redirections + // but as it opens a connection, it's less useful than you think. +// return operations.openConnectionRedirecting(url); + return operations.openConnection(url); } catch (AuthenticationException e) { throw new IOException(e); @@ -124,10 +129,11 @@ public class UgiJerseyBinding implements ClientResponse response = ex.getResponse(); int resultCode = response.getStatus(); String msg = verb.toString() + " " + url; - if (resultCode == 404) { + if (resultCode == HttpServletResponse.SC_NOT_FOUND) { return (IOException) new PathNotFoundException(url).initCause(ex); } - if (resultCode == 401) { + if (resultCode == HttpServletResponse.SC_UNAUTHORIZED + || resultCode == HttpServletResponse.SC_FORBIDDEN) { return (IOException) new PathAccessDeniedException(url).initCause(ex); } // all other error codes http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/6c038b41/slider-core/src/main/java/org/apache/slider/core/restclient/UrlConnectionOperations.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/core/restclient/UrlConnectionOperations.java b/slider-core/src/main/java/org/apache/slider/core/restclient/UrlConnectionOperations.java index 328684e..e6b08c1 100644 --- a/slider-core/src/main/java/org/apache/slider/core/restclient/UrlConnectionOperations.java +++ b/slider-core/src/main/java/org/apache/slider/core/restclient/UrlConnectionOperations.java @@ -31,10 +31,13 @@ import org.apache.hadoop.yarn.webapp.NotFoundException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.HttpHeaders; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; +import java.net.URI; import java.net.URL; /** @@ -74,7 +77,8 @@ public class UrlConnectionOperations extends Configured { } /** - * Opens a url with read and connect timeouts + * Opens a url with cache disabled, redirect handled in + * (JDK) implementation. * * @param url to open * @return URLConnection @@ -84,14 +88,70 @@ public class UrlConnectionOperations extends Configured { public HttpURLConnection openConnection(URL url) throws IOException, AuthenticationException { - Preconditions.checkArgument(url.getPort() != 0, "no port"); - HttpURLConnection conn = - (HttpURLConnection) connectionFactory.openConnection(url, useSpnego); + + HttpURLConnection conn = innerOpenConnection(url); conn.setUseCaches(false); conn.setInstanceFollowRedirects(true); return conn; } + + /** + * Opens a url. + * <p> + * This implementation + * <ol> + * <li>Handles protocol switching during redirects</li> + * <li>Handles 307 responses "redirect with same verb"</li> + * </ol> + * + * @param url to open + * @return URLConnection + * @throws IOException + * @throws AuthenticationException authentication failure + */ + public HttpURLConnection openConnectionRedirecting(URL url) throws + IOException, + AuthenticationException { + HttpURLConnection connection = innerOpenConnection(url); + connection.setUseCaches(false); + int responseCode = connection.getResponseCode(); + if (responseCode == HttpServletResponse.SC_MOVED_TEMPORARILY + || responseCode == HttpServletResponse.SC_TEMPORARY_REDIRECT) { + log.debug("Redirected with response {}", responseCode); + // is a redirect - are we changing schemes? + String redirectLocation = connection.getHeaderField(HttpHeaders.LOCATION); + String originalScheme = url.getProtocol(); + String redirectScheme = URI.create(redirectLocation).getScheme(); + boolean buildNewUrl = false; + if (!originalScheme.equals(redirectScheme)) { + // need to fake it out by doing redirect ourselves + log.debug("Protocol change during redirect"); + buildNewUrl = true; + } else if (responseCode == HttpServletResponse.SC_TEMPORARY_REDIRECT) { + // 307 response + buildNewUrl = true; + } + + if (buildNewUrl) { + // perform redirect ourselves + log.debug("Redirecting {} to URL {}", + url, redirectLocation); + URL redirectURL = new URL(redirectLocation); + connection = innerOpenConnection(url); + } + } + + return connection; + } + + protected HttpURLConnection innerOpenConnection(URL url) throws + IOException, + AuthenticationException { + Preconditions.checkArgument(url.getPort() != 0, "no port"); + return (HttpURLConnection) connectionFactory.openConnection(url, useSpnego); + } + public HttpOperationResponse execGet(URL url) throws IOException, AuthenticationException { @@ -121,7 +181,6 @@ public class UrlConnectionOperations extends Configured { if (doOutput) { conn.setRequestProperty("Content-Type", contentType); } - // now do the connection conn.connect();
