4

My code (below) tries to get the final URL returned from a server that does a bit of redirecting. It works fine as long as the URLs have an http scheme. My problem arises when I want to return a URL with a different scheme. Ultimately I want, in some situations, to return a market:// url or other app launch schemes since this is for Android and I want to start Intents with them.

So this gets me as far as retrieving the final http url, but when the final url is market:// it throws the exception seen (java.lang.IllegalStateException: Scheme 'market' not registered), and then getURI doesn't provide that one, it'll provide whatever was before that.

    DefaultHttpClient client = new DefaultHttpClient();
    HttpContext httpContext = new BasicHttpContext();
    HttpGet httpGet = new HttpGet(mInitialUrl);

    try {
        client.execute(httpGet, httpContext);
    } catch (IllegalStateException e) {
        e.printStackTrace();
    }

    // Parse out the final uri. 
    HttpHost currentHost = (HttpHost) httpContext.getAttribute(ExecutionContext.HTTP_TARGET_HOST);
    HttpUriRequest req = (HttpUriRequest) httpContext.getAttribute(ExecutionContext.HTTP_REQUEST);

    return (req.getURI().isAbsolute()) ? req.getURI().toString() : (currentHost.toURI() + req.getURI());

Now, I could just register market:// as a scheme, but I don't want to hard-code beforehand what the valid schemes are, I just want it to accept them and return them whatever they are.

Any ideas? Maybe I'm not even taking the right approach. (Changing the server behavior isn't an option in this case... I've got to just deal with the redirects.)

My hope is that someone can tell me how to get the HttpClient to ignore the scheme, or at least preserve the final URI it tries to access.

Turnsole
  • 3,422
  • 5
  • 30
  • 52

1 Answers1

3

Using HttpURLConnection for the job works for me. The following of redirects stops without exception when the target resource is not a HTTP resource.

HttpURLConnection connection = (HttpURLConnection) new URL(mInitialUrl).openConnection();
connection.setInstanceFollowRedirects(true);
String location = connection.getHeaderField("location");
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    connection.getHeaderField("location") is always null for me. I tried inserting connection.connect(), but no luck. – Turnsole Feb 16 '13 at 00:02
  • Funny thing... if I change setInstanceFollowRedirects to false then it provides the redirect value for "location". Apparently the location is part of the redirect header, which it wouldn't get if it followed the redirect automatically? (My clue was here: http://stackoverflow.com/questions/3786161/cant-get-response-header-location-using-javas-urlconnection.) – Turnsole Feb 27 '13 at 20:43
  • The problem there being multiple redirects. I can get the first redirect, but since it doesn't follow it to the end then I can not get the final one. – Turnsole Feb 27 '13 at 20:54
  • 1
    That's exactly why `setInstanceFollowRedirects()` was set to `true`. As to why you got `null` in the end, sorry I can't reproduce it in Oracle Java 1.7.0_10. Your best bet would be to disable following of redirects and connect in a loop as long as you find a `Location` header which points to a HTTP(S) resource. – BalusC Feb 27 '13 at 20:56
  • So following that suggestion I discovered that one of the redirects failed to set a valid Location header field (the url wasn't properly encoded). Problem solved! Thanks for your help. – Turnsole Feb 27 '13 at 21:05
  • This returns null when using the following url goo.gl/hMi9zL but it follows the redirects for this one skl.sh/thomasfrank11 will work just as expected. I noticed that for the goo.gl url I had to use connection.getUrl() instead – Jonathan Morales Vélez Dec 07 '18 at 11:56