248

Dave Ward says,

It’s not exactly light reading, but section 4.2 of RFC 3986 provides for fully qualified URLs that omit protocol (the HTTP or HTTPS) altogether. When a URL’s protocol is omitted, the browser uses the underlying document’s protocol instead.

Put simply, these “protocol-less” URLs allow a reference like this to work in every browser you’ll try it in:

//ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js

It looks strange at first, but this “protocol-less” URL is the best way to reference third party content that’s available via both HTTP and HTTPS.

This would certainly solve a bunch of mixed-content errors we're seeing on HTTP pages -- assuming that our assets are available via both HTTP and HTTPS.

Is this completely cross-browser compatible? Are there any other caveats?

Community
  • 1
  • 1
a paid nerd
  • 30,702
  • 30
  • 134
  • 179
  • I readed about this technique at IE blog a while ago. But when I tried it din't work quite well. If my site was served with HTTPS, the browser (Chrome) was still using HTTP for protocol-less URLs. – Christopher Ramírez Jun 09 '12 at 17:05
  • 11
    WARNING: remember to NEVER user schemeless URIs in HTTP 3xx redirects!! HTTP headers are not compatible with this URL format. If you need to redirect depending on scheme, use mod_rewrite or similar. – user2596282 Jul 18 '13 at 15:44
  • 1
    @user2596282 Experimentation in modern versions of Chrome and Firefox disagrees with you, as does the (still in draft) revision to the HTTP 1.1. spec defined by the HTTPbis working group (see https://svn.tools.ietf.org/svn/wg/httpbis/draft-ietf-httpbis/latest/p2-semantics.html#header.location ). Perhaps what you say is true of some browsers, though; do you know of any in particular that fail on protocol-relative URLs in location headers? – Mark Amery Jul 21 '13 at 19:06
  • Same question with some good answers: [Absolute URLs omitting the protocol (scheme) in order to preserve the one of the current page](http://stackoverflow.com/questions/4978235/absolute-urls-omitting-the-protocol-scheme-in-order-to-preserve-the-one-of-the) – Álvaro González Feb 05 '14 at 16:56
  • Don't use them, they are ugly and redundant. – IS4 Aug 10 '14 at 23:33
  • Possible duplicate of [Is it valid to replace http:// with // in a – bg17aw Jun 07 '16 at 09:52

7 Answers7

205

I tested it thoroughly before publishing. Of all the browsers available to test against on Browsershots, I could only find one that did not handle the protocol relative URL correctly: an obscure *nix browser called Dillo.

There are two drawbacks I've received feedback about:

  1. Protocol-less URLs may not work as expected when you "open" a local file in your browser, because the page's base protocol will be file:///. Especially when you're using the protocol-less URL for an external resource like a CDN-hosted asset. Using a local web server like Apache or IIS to test against http://localhost addresses works fine though.
  2. Apparently there's at least one iPhone feed reader app that does not handle the protocol-less URLs correctly. I'm not aware of which one has the problem or how popular it is. For hosting a JavaScript file, that's not a big problem since RSS readers typically ignore JavaScript content anyway. However, it could be an issue if you're using these URLs for media like images inside content that needs to be syndicated via RSS (though, this single reader app on a single platform probably accounts for a very marginal number of readers).
Dave Ward
  • 59,815
  • 13
  • 117
  • 134
  • 33
    While IE7/8 handles protocol-relative URLs (aka. schemeless URIs) well in most cases, when stylesheets are specified with such URLs, it will download them _twice_. (So says [Steve Souders](http://www.stevesouders.com/blog/2010/02/10/5a-missing-schema-double-download/)) – lucasrizoli Apr 29 '11 at 20:48
  • 3
    I'm finding that IE6 attempts to convert the URI to a relative one (i.e. removing one of the leading slashes). This is in a `link` element. For example, when specifying `//fonts.googleapis.com/css?family=Rokkitt:400,700`, IE6 tries to load `http://mysite.com/fonts.googleapis.com/css/<...>`. Not so good! – CBono Sep 28 '11 at 13:55
  • 2
    I've found from my logs instances of what seem to be web spider robots (source unknown) trying to use the protocol-less links and not handling them correctly as well. – Kzqai Oct 13 '11 at 16:25
  • 3
    I've seen a lot of that in my logs, unrelated to protocol-less URLs. A lot of those spiders are just incredibly poorly written. – Dave Ward Oct 13 '11 at 18:13
  • @CBono: //fonts.googleapis.com/family=... seems to work fine on IE6. Can you elaborate how to reproduce the problem? Does any one else have problems with IE6 and protocol relative URLs? – Jan M Aug 03 '12 at 17:03
  • @CBono is this still a problem for IE6? I have no way to test. – Hope4You Sep 21 '12 at 17:56
  • @Hope4You Yes, I recently attempted to convert a page over to use protocol-less URLs and had pretty bad results. – CBono Sep 21 '12 at 18:12
  • @JanM I have seen occasions where IE6 doesn't misinterpret these links, but more often than not it does. So there's some conditions, that I don't understand, that affect the behavior. Overall, it seems pretty delicate and I wouldn't trust IE6 to load these URLs correctly. – CBono Sep 21 '12 at 18:13
  • @CBono if `//file` doesn't work, would `/file` work for all browsers? – Hope4You Sep 21 '12 at 18:20
  • 1
    @Hope4You No, because then ALL browsers would interpret that as a relative link, rather than an absolute protocol-less link. – CBono Sep 21 '12 at 18:35
  • @CBono Isn't what I've shown an absolute link? I thought that's what 1 slash does. – Hope4You Sep 21 '12 at 19:05
  • 11
    It's important to understand that these URLs are **not** protocol-_less_, but protocol-_relative_. They get their protocol from their context, and lacking a context they will act like file urls in most browsers, effectively meaning they break in that they will not load the intended content. While they will work when delivered over http, you'll find that if you save the page and load the exact same HTML from a local file, they will not, because the context is different. The only contexts you should use them in is http vs https. – Synchro Jan 30 '13 at 07:11
  • +1, but I'm curious, did your testing include handling protocol-relative links in 301 and 301 redirect headers? – Patrick M May 02 '14 at 20:28
  • 1
    @PatrickM: I did not test redirects, no. Only loading JavaScript from the Google CDN. – Dave Ward May 02 '14 at 22:38
  • Bingbot is a bad player, getting requests for http://domain.tld/www.someotherdomain.com/path Headers From: bingbot(at)microsoft.com, User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) Real request coming from PTR to domain search.msn.com (A record also resolving back properly) – NiKiZe Aug 13 '14 at 17:07
  • 1
    I wouldn't call Dillo "obscure" only because you never heard of it. It's a fine browser when you need to (or want to) go really minimal, without falling back to text only browsers like e.g. lynx. – Sebastian Mach Apr 14 '15 at 13:01
39

The question of whether one could change all their links to be protocol-relative may be moot, considering the question of whether one should do so. According to Paul Irish:

2014.12.17: Now that SSL is encouraged for everyone and doesn’t have performance concerns, this technique is now an anti-pattern. If the asset you need is available on SSL, then always use the https:// asset.

James Skemp
  • 8,018
  • 9
  • 64
  • 107
Ohad Schneider
  • 36,600
  • 15
  • 168
  • 198
  • I was thinking exactly the same. What's the point in downloading an external asset over http if it's available over https as well - even if the main site is using http (which it shouldn't, but that's another topic). – joonas.fi Aug 18 '15 at 12:55
  • 1
    @joonas.fi the only thing I can think of is avoiding mixed HTTP/HTTPS warnings that might be generated by some browsers – Ohad Schneider Aug 18 '15 at 13:13
  • 3
    @Ohad_Schneider warnings are triggered only if the document is loaded over secure(https) but assets over unsecure(http). What I was suggesting is that you can always load assets over secure, even if the document is loaded over unsecure. There's no warning and no reason not to use secure, rendering the whole "protocol-relative URL" unnecessary. – joonas.fi Aug 19 '15 at 13:36
  • 1
    @Ohad_Schneider oh sorry, I think I misinterpreted what you were saying. Loading assets over https when you document is over http should not produce any warnings. But loading assets over http when your document is over https does (and probably is blocked by default, at least in Chrome). Were you referring to the case where you serve your site over https and external assets are available only under http? Yeah, that could be an issue but I don't think there's any serious 3rd party service that doesn't serve their content over https, or else they should go out of business anyway. :) – joonas.fi Aug 19 '15 at 13:44
  • @joonas.fi Wut? O_o If someone has HTTPSed site (then) protocol relative URLs won't help to solve getting 3rd party assets over HTTP — no way. And anyways it's better having not that clean-green SSL logo on your HTTPS page than give it up to HTTP back again just due to 3rd parties don't support HTTPS yet. – poige Sep 24 '15 at 20:08
  • @poige I'm not sure if I understand you correctly, but if you're saying that it's ok to load HTTP content from HTTPS domain (= mixed content), then you're probably wrong, as browsers are blocking mixed content (and for a good reason, as mixed content defeats the security of your page as it leaves the user vulnerable to man-in-the-middle attacks). See: https://blog.mozilla.org/tanvi/2013/04/10/mixed-content-blocking-enabled-in-firefox-23/ And like I said, if the 3rd party in 2015 does not support HTTPS, then they're probably not trustworthy anyways. One can get HTTPS for free, so why not use it – joonas.fi Sep 25 '15 at 13:49
  • @poige your assumption that it's better to load http content because some third party don't support https rendering them useless when using https is ridiculous. If you load the document under http, you're making yourself vulnerable to attacks that simply can load any secure/non secure assets. – Loïc Faure-Lacroix Apr 07 '17 at 16:49
30

If you use protocol-less URLs to load stylesheets, IE 7 & 8 will download them twice: http://www.stevesouders.com/blog/2010/02/10/5a-missing-schema-double-download/

So, this is to be avoided for CSS if you like good performance.

Tim Beadle
  • 307
  • 3
  • 5
  • 5
    True, however this becomes less and less of a reason to avoid using schemeless URLs as the market share of IE 7 & 8 shrinks. – Simon Lieschke Sep 18 '13 at 04:51
15

Yes, network-path references were already specified in RFC 1808 and should work with all browsers.

Community
  • 1
  • 1
Gumbo
  • 643,351
  • 109
  • 780
  • 844
4

Is this completely cross-browser compatible? Are there any other caveats?

Just to throw this in the mix, if you are developing on a local server, it might not work. You need to specify a scheme, otherwise the browser may assume that src="//cdn.example.com/js_file.js" is src="file://cdn.example.com/js_file.js", which will break since you're not hosting this resource locally.

Microsoft Internet Explorer seem to be particularly sensitive to this, see this question: Not able to load jQuery in Internet Explorer on localhost (WAMP)

You would probably always try to find a solution that works on all your environments with the least amount of modifications needed.

The solution used by HTML5Boilerplate is to have a fallback when the resource is not loaded correctly, but that only works if you incorporate a check:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<!-- If jQuery is not defined, something went wrong and we'll load the local file -->
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.10.2.min.js"><\/script>')</script>

I posted this answer here as well.

UPDATE: HTML5Boilerplate now uses <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"> after deciding to deprecate protocol relative URLs, see here.

Community
  • 1
  • 1
bg17aw
  • 2,818
  • 1
  • 21
  • 27
  • 1
    As of 2022, developing from `file://` URLs doesn't really work anymore. Modern browsers won't even run JavaScript from local HTML files because doing so has enabled so many security vulnerabilities. Since you can't develop with local files anymore, it is no longer a reason to avoid protocol relative links. – Stephen Ostermiller Aug 18 '22 at 15:15
1

I have not had these issues when using ://example.com - but you do need to add the colon at the beginning. Yoast had a good write up about this a while back. But it's lost in his pile of blog posts.

Stephen Ostermiller
  • 23,933
  • 14
  • 88
  • 109
  • down-vote for not stating where the additional : is useful. Everywhere I accidentally left the ":" broke the link – rob Mar 12 '19 at 14:49
1

If you would like to make sure all requests are upgraded to secure protocol then there is simple option to use Content Security Policy header upgrade-insecure-requests

Content-Security-Policy: upgrade-insecure-requests;

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/upgrade-insecure-requests

mybrave
  • 1,662
  • 3
  • 20
  • 37