Breaking with protocol

Are you or your users are getting a “This page contains both secure and nonsecure items” message in Internet Explorer?

This page contains both secure and nonsecure items: Do you want to display the nonsecure items?

You might mistakenly believe that it is a problem isolated to IE, but if you check the bottom right corner of Firefox you’ll see that all is not well there either:

The issue here is a simple one to understand. The browser is rendering a page over SSL denoted by the https:// protocol in the address bar. However, there are elements within that page that are being served via the nonsecure http:// protocol. These elements may be images, frames, stylesheets, javascript, etc

By now you might be asking how you can serve up resources to visitors over either protocol without maintaining separate sites or stylesheets. The most obvious and easiest way to accomplish this has been to change any absolute URLs to relative paths.

Change:


<img src="http://www.example.com/images/header.png" />
div#header {
  background-image: url(http://www.example.com/images/header.png) no-repeat;
}

To:


<img src="/images/header.png" />
div#header {
  background-image: url(/images/header.png) no-repeat;
}

However, what happens if you maintain your static files on a separate server or sub-domain and you can not link to them using a relative URL? Is it possible to still maintain a single stylesheet (assuming, of course, that both sites are secured by trusted certificate)?

I think so, yes. You can link to things in a sudo-absolute manner by omitting the leading protocol. For example:


<img src="//www.example.com/images/header.png" />
div#header {
  background-image: url(//www.example.com/images/header.png) no-repeat;
}

I’ve only done limited testing on IE and Firefox thus far, but it seems to work fine. I’m curious to hear anyone’s thoughts on the pros and cons of this method. Interestingly, it’s difficult to find anything that been written about this on th web. All the keywords I try bring up nothing but whitepapers and RFCs.

Update: 01.23.2008 5:40pm

Ok, so after digging and digging and digging I’ve finally found what I’m looking for! This behavior is, in fact, in the HTTP 1.1 standard as specified in RFC 2068 and RFC 2396:


   URIs in HTTP can be represented in absolute form or relative to some
   known base URI, depending upon the context of their use. The two
   forms are differentiated by the fact that absolute URIs always begin
   with a scheme name followed by a colon.

          URI            = ( absoluteURI | relativeURI ) [ "#" fragment ]

          absoluteURI    = scheme “:” *( uchar | reserved )

          relativeURI    = net_path | abs_path | rel_path

          net_path       = “//” net_loc [ abs_path ]
          abs_path       = “/” rel_path
          rel_path       = [ path ] [ ";" params ] [ "?" query ]

When specifying a relativeURI, the most common usages are the abs_path and rel_path like the following:


/* abs_path */
div#header {
  background-image: url(/images/header.png) no-repeat;
}
<!-- rel_path -->
<img src="images/tree.jpg" alt="Oak" />

However, using net_path to optionally include the http: or https: is apparently perfectly valid as well. It’s so obscure or rarely used that a Google search for “net_path” will suggest that you correct your search to “set_path”.

It looks funny and it feels wrong, but it works.