HttpClient redirecting to URL with spaces throwing exception
The Apache HTTP library allows you to register a RedirectHandler object that will get invoked whenever a redirect occurs. You can use this to intercept the redirect and fix it.
(That being said, the site that's sending you this redirect is broken. You should contact them and let them know.)
class CustomRedirectHandler extends DefaultRedirectHandler { public URI getLocationURI(HttpResponse response, HttpContext context) { // Extract the Location: header and manually convert spaces to %20's // Return the corrected URI }}DefaultHttpClient httpClient = new DefaultHttpClient();RedirectHandler customRedirectHandler = new CustomRedirectHandler();//...httpClient.setRedirectHandler(customRedirectHandler);
Here is my working code :)
class spaceRedirectHandler extends DefaultRedirectHandler{ private static final String REDIRECT_LOCATIONS = "http.protocol.redirect-locations"; public spaceRedirectHandler() { super(); } public boolean isRedirectRequested( final HttpResponse response, final HttpContext context) { if (response == null) { throw new IllegalArgumentException("HTTP response may not be null"); } int statusCode = response.getStatusLine().getStatusCode(); switch (statusCode) { case HttpStatus.SC_MOVED_TEMPORARILY: case HttpStatus.SC_MOVED_PERMANENTLY: case HttpStatus.SC_SEE_OTHER: case HttpStatus.SC_TEMPORARY_REDIRECT: return true; default: return false; } //end of switch } public URI getLocationURI( final HttpResponse response, final HttpContext context) throws ProtocolException { if (response == null) { throw new IllegalArgumentException("HTTP response may not be null"); } //get the location header to find out where to redirect to Header locationHeader = response.getFirstHeader("location"); if (locationHeader == null) { // got a redirect response, but no location header throw new ProtocolException( "Received redirect response " + response.getStatusLine() + " but no location header"); }//HERE IS THE MODIFIED LINE OF CODE String location = locationHeader.getValue().replaceAll (" ", "%20"); URI uri; try { uri = new URI(location); } catch (URISyntaxException ex) { throw new ProtocolException("Invalid redirect URI: " + location, ex); } HttpParams params = response.getParams(); // rfc2616 demands the location value be a complete URI // Location = "Location" ":" absoluteURI if (!uri.isAbsolute()) { if (params.isParameterTrue(ClientPNames.REJECT_RELATIVE_REDIRECT)) { throw new ProtocolException("Relative redirect location '" + uri + "' not allowed"); } // Adjust location URI HttpHost target = (HttpHost) context.getAttribute( ExecutionContext.HTTP_TARGET_HOST); if (target == null) { throw new IllegalStateException("Target host not available " + "in the HTTP context"); } HttpRequest request = (HttpRequest) context.getAttribute( ExecutionContext.HTTP_REQUEST); try { URI requestURI = new URI(request.getRequestLine().getUri()); URI absoluteRequestURI = URIUtils.rewriteURI(requestURI, target, true); uri = URIUtils.resolve(absoluteRequestURI, uri); } catch (URISyntaxException ex) { throw new ProtocolException(ex.getMessage(), ex); } } if (params.isParameterFalse(ClientPNames.ALLOW_CIRCULAR_REDIRECTS)) { RedirectLocations redirectLocations = (RedirectLocations) context.getAttribute( REDIRECT_LOCATIONS); if (redirectLocations == null) { redirectLocations = new RedirectLocations(); context.setAttribute(REDIRECT_LOCATIONS, redirectLocations); } URI redirectURI; if (uri.getFragment() != null) { try { HttpHost target = new HttpHost( uri.getHost(), uri.getPort(), uri.getScheme()); redirectURI = URIUtils.rewriteURI(uri, target, true); } catch (URISyntaxException ex) { throw new ProtocolException(ex.getMessage(), ex); } } else { redirectURI = uri; } if (redirectLocations.contains(redirectURI)) { throw new CircularRedirectException("Circular redirect to '" + redirectURI + "'"); } else { redirectLocations.add(redirectURI); } } return uri; } }
I recommend creating custom redirect strategy
class CustomRedirectStrategy extends DefaultRedirectStrategy { // NOTE: Hack for bad redirects such as: http://www.healio.com/Rss/Allergy%20Immunology override def createLocationURI(location: String): URI = { try { super.createLocationURI(location) } catch { case ex: ProtocolException => val url = new URL(location) val uri = new URI(url.getProtocol, url.getUserInfo, url.getHost, url.getPort, url.getPath, url.getQuery, url.getRef) uri } }}
that you can set in your client via setRedirectStrategy
method.
HttpAsyncClients.custom.setRedirectStrategy(new CustomRedirectStrategy).build