Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HttpURLConnection - "https://" vs. "http://"

I'm trying to get the favicon of the url the user enters, for example

_url = "google.com";

I use HttpUrlConnection to get the Bitmap of the favicon from the /favicon.ico extension from the host url.

        String faviconString = Uri.parse(_url).getHost() + "/favicon.ico";
        URL faviconUrl = null;
        Bitmap favicon = null;
        try
        {
            faviconString = "http://" + faviconString;
            faviconUrl = new URL(faviconString);
            HttpURLConnection connection = (HttpURLConnection) faviconUrl.openConnection();
            connection.setDoInput(true);
            connection.connect();
            favicon = BitmapFactory.decodeStream(connection.getInputStream());
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        return favicon;

However, since the user probably won't specify http:// or https://, I would have to add it myself. The problem I'm having is that, if I add http:// in front of the url, everything would work fine, but for https://, some sites would return the favicon, others would just give me null. How do I find out which page uses https? Should I just add http:// for every case? Are there any websites that restricts to strictly https and would return null for using http?

like image 489
Jason Hu Avatar asked Sep 20 '13 14:09

Jason Hu


People also ask

Can I use HttpURLConnection for https?

It can cover Https addresses also, because HttpsURLConnection extends this.

What is the difference between URLConnection and HttpURLConnection?

URLConnection is the base class. HttpURLConnection is a derived class which you can use when you need the extra API and you are dealing with HTTP or HTTPS only. HttpsURLConnection is a 'more derived' class which you can use when you need the 'more extra' API and you are dealing with HTTPS only.

Is HttpURLConnection thread safe?

Each instance of HttpURLConnection may be used for one request/response pair. Instances of this class are not thread safe.

Is HttpURLConnection synchronous?

An implementation of SdkHttpClient that uses HttpURLConnection to communicate with the service. This is the leanest synchronous client that optimizes for minimum dependencies and startup latency in exchange for having less functionality than other implementations.


2 Answers

Unless you use user2558882's idea or there is some other tool out in the wild that will just get a websites favicon for you, you're going to have to check both the http and https urls. There is no other way to do this. It is part of the difficulty of using the web.

Perhaps looking at your code differently and breaking down what you're trying to do into smaller more manageable parts would be a bit better?

public void getFavicon(String host) {

    URL httpUrl = this.getHttpUrl(host + "/favicon.ico");

    Bitmap favicon = this.getBitmap(httpUrl);

    if (favicon == null) {

        URL httpsUrl = this.getHttpsUrl(host + "/favicon.ico");

        favicon = this.getBitmap(httpsUrl);
    }

    if (favicon == null) {

        throw new FaviconMissingException("Unable to find favicon for host: " + host);
    }

    return favicon;
}

public URL getHttpUrl(String uri) throws MalformedURLException {

    // There are better ways of building a url then string concationation.
    return new URL("http://" + uri);
}

public URL getHttpsUrl(String uri) throws MalformedURLException {

    // There are better ways of building a url then string concationation.
    return new URL("https://" + uri);
}

public Bitmap getBitmap(URL url) {

    InputStream inputStream = getInputStream(url);

    Bitmap bitmap = BitmapFactory.decodeStream(inputStream);

    return bitmap
}

public InputStream getInputStream(URL url) {

    // Please use a real connection library like HTTPClient here!
    // HttpClient will handle timeouts, redirects, and things like that for you.
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setDoInput(true);
    connection.connect();

    return connection.getInputStream();
}

BTW, being concerned about one or two connections takes more time then writing the code to make two requests. I almost guarantee that google is making two requests as needed. And if it is good enough for google it is good enough for me.

Finally, if you start to see that making two requests is really taking too much time, then do something about improving the performance.

like image 176
hooknc Avatar answered Oct 05 '22 22:10

hooknc


Note: I am not sure how helpful my answer would be.

You can grab the favicon using google:

http://www.google.com/s2/favicons?domain=stackoverflow.com

returns:

enter image description here

You don't have to specify http or https.

 http://www.google.com/s2/favicons?domain=my.yorku.ca ===>> (https://my.yorku.ca)

returns:

enter image description here

But this is not the actual favicon that https://my.yorku.ca uses. So, I guess google returns a default one for sites that do not provide access their favicons.

InputStream is = null;

String urlPrefix = "http://www.google.com/s2/favicons?domain=";

String _url = "google.com";

Bitmap favicon = null;

try {

    is = (InputStream) new URL(urlPrefix + _url).getContent();

} catch (MalformedURLException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

favicon = BitmapFactory.decodeStream(is);

You can actually keep a copy of the default favicon and check if:

if (defaultBitmap.sameAs(favicon)) {
    // favicon wasn't available
}
like image 40
Vikram Avatar answered Oct 06 '22 00:10

Vikram