Download and Buy Now Link

Using Protocol Relative URLs to Switch between HTTP and HTTPS

February 10, 2010

Attempting to use HTTP resources on an secure web page is a guaranteed way to annoy IE users, because it generates a confusing security warning for anyone running with the default IE settings. Our previous post on fixing this message in IE 8 is responsible for more than 50% of the traffic and comments on this blog. Hopefully, Microsoft will take note and change this in a future version of IE.

In the meantime, it’s important to avoid this warning by ensuring that every image, CSS and Javscript file on a secure page is accessed using HTTPS. For content on the same domain it’s quite straightforward – you just need to use relative URLs. A relative URL contains the ‘offset’ URL that needs to be applied to the page’s absolute URL in order to find a resource.

For example, here’s a screen shot from HttpWatch accessing our home page over HTTPS:

HttpWatch Home Page Access with HTTPS

Searching for one of the images in HttpWatch shows that it was specified with a relative URL and the switch to HTTPS happened automatically:

Relative URL

A problem arises though, if you attempt to access a resource from a different domain because you can’t use the simple path-relative URL to access the resource. This often happens when you attempt to use a third party service such as Google Analytics or a third party Ajax library CDN.

Google Analytics solves the problem with its external javascript file by recommending the use of this code to dynamically switch protocols:

var gaJsHost = (("https:" == document.location.protocol) ?
    "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost +
    "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));

Another solution is to hard code the external resource with an HTTPS based URL regardless of how the containing page is accessed. This avoids any security warnings in IE, but does mean that the HTTPS resource download will consume more CPU resources in cases where the HTTP download would have been sufficient.

The solution we prefer to use is to specify a Protocol Relative URL. It’s just like a regular URL except that you leave out the protocol prefix. For example, when Microsoft recently announced SSL support for their Ajax CDN the recommended script tag for secure pages was:

<script src=”https://ajax.microsoft.com/ajax/jquery/jquery-1.3.2.min.js” type=”text/javascript”></script>

But if you change this to a protocol relative URL:

<script src=”//ajax.microsoft.com/ajax/jquery/jquery-1.3.2.min.jstype=”text/javascript”></script>

You get the automatic use of HTTPS on secure pages and avoid the overhead of HTTPS on non-secure pages.

We put together a simple jQuery demo page using this technique. In HttpWatch, you can see that the resource is automatically downloaded with HTTP for non-secure access:

and HTTPS with secure access:

One downside of this approach is that there will be separate cached copies for both the HTTP and HTTPS based URLs. If a vistor to your site first uses a non-secure HTTP based URL and then switches to HTTPS they would have to download fresh copies of resources that had already been accessed over HTTP.

UPDATE: Steve Souders pointed out another downside to using protocol relative URLs; they cause a double download of CSS files in IE 7 & 8.

22 Comments