Is it valid to replace http:// with // in a <script src="http://...">?
Asked Answered
E

14

481

I have the following element:

<script type="text/javascript" src="https://cdn.example.com/js_file.js"></script>

In this case the site is HTTPS, but the site may also be just HTTP. (The JS file is on another domain.) I'm wondering if it's valid to do the following for convenience sake:

<script type="text/javascript" src="//cdn.example.com/js_file.js"></script>

I'm wondering if it's valid to remove the http: or https:?

It seems to work everywhere I have tested, but are there any cases where it doesn't work?

Elodiaelodie answered 15/2, 2009 at 0:15 Comment(9)
Can the "it seems to work everywhere" be generalised to images, iframes, link-rels etc etc? This is interesting stuff, if so.Andress
Yup, it should work in any place that calls for a URI: images, links, etc. It may be rare to see this in use, but it's perfectly valid.Larisa
Whats with all that instant upvoting guys? Not that the question is bad or anything, I'm just curious. But I bet Chris' intial reputation have an influence.Quadrivium
@Frederik: Because it's a fascinating and useful trick that most people are apparently unaware of.Worthen
@Frederik: What?Worthen
@Fred I haven't seen such a trend even after I crossed 10KAmherst
I don't exactly know when this happens, but i did get lots of these errors in my log: [Fri May 15 17:14:09 2015] [error] [client 32.104.18.214] File does not exist: /www/html/ajax.googleapis.com, referer: http://example.com/something - for that reason I switched back to adding the protocolCystotomy
Here's a scenario where it doesnt work: stackoverflow.com/questions/40161670/…Grouchy
Possible duplicate of URI starting with two slashes ... how do they behave?Gobioid
L
399

A relative URL without a scheme (http: or https:) is valid, per RFC 3986: "Uniform Resource Identifier (URI): Generic Syntax", Section 4.2. If a client chokes on it, then it's the client's fault because they're not complying with the URI syntax specified in the RFC.

Your example is valid and should work. I've used that relative URL method myself on heavily trafficked sites and have had zero complaints. Also, we test our sites in Firefox, Safari, IE6, IE7 and Opera. These browsers all understand that URL format.

Larisa answered 15/2, 2009 at 0:39 Comment(17)
That doesn't appear to be a relative URL in the question. It looks like an absolute URL that's missing the protocol.Bewail
It is indeed relative. Take a look at RFC 3986, section 4.Larisa
I agree its relative, // == / relative begins with / absolute does not. So cdn.example.com/js_file.js is absolute but /cdn.example.com/js_file.js or //cdn.example.com/js_file.js is relative.Multinational
"If a client chokes on it, then it's the client's fault because they're not complying with the URI syntax specified in the RFC." -- I think this is an interesting question -- but whether a client follows "the spec" is hardly a good standard for whether it's wise to do in a web app.Dolan
Although this technique seems to be little known, it is supported in all the web browsers. It works just great.Barneybarnhart
I wonder why google doesn't use this for analytics. They use the document.location.protocol method.Elodiaelodie
When they say relative URL, it means relative as in on the same protocol.Holton
@Darryl Hein I believe google uses the document.location.protocol method because it also modifies the url, not only the scheme. They go to SSL.google-analytics.com if the document is using the https scheme.Schellens
google doesn't use this because Windows XP network stack doesn't support SNI. See here: blogs.msdn.com/b/ieinternals/archive/2009/12/07/… . Therefore allowing the google analytics script to be loaded through https on IE6 would result in a certificate error.Chemosphere
@Eilistraee, very nice find! I even think that's an answer in itself, as it is something to consider, despite this being 2012.Butene
@Chemosphere the URL Google choose to use for their Analytics service has nothing to do with SNI. SNI is about having the server distinguishing requests to distinct hosts on the same IP address and port. http:// and https:// have distinct default ports already.Interpellant
yes, but I was speaking of the use of the subdomain ssl.google-analytics.com by Google. It's because if they simply used google-analytics.com, the Google server would resolve the host through SNI, which doesn't work if using WinXP & IE. Therefore, they created the ssl.google-analytics.com subdomain.Chemosphere
I love this trick. I should mention it can be a pain if you ever need to access the file from your filesystem. Then the relative url resolves to the "file" scheme, which of course doesn't work.Harm
It should also be mentioned that this standard doesn't validate on XHTML webpages.Etruria
I'm having same issue on my localhost. Everywhere else relative proto url works except localhost.Taub
Does this Apply to img src tags?Cornfield
@TOMP I believe it'll apply to anywhere you use a URL in HTML. script, a, img, etc.Larisa
I
157

It is guaranteed to work in any mainstream browser (I'm not taking browsers with less than 0.05% market share into consideration). Heck, it works in Internet Explorer 3.0.

RFC 3986 defines a URI as composed of the following parts:

     foo://example.com:8042/over/there?name=ferret#nose
     \_/   \______________/\_________/ \_________/ \__/
      |           |            |            |        |
   scheme     authority       path        query   fragment

When defining relative URIs (Section 5.2), you can omit any of those sections, always starting from the left. In pseudo-code, it looks like this:

 result = ""

  if defined(scheme) then
     append scheme to result;
     append ":" to result;
  endif;

  if defined(authority) then
     append "//" to result;
     append authority to result;
  endif;

  append path to result;

  if defined(query) then
     append "?" to result;
     append query to result;
  endif;

  if defined(fragment) then
     append "#" to result;
     append fragment to result;
  endif;

  return result;

The URI you are describing is a scheme-less relative URI.

Idem answered 4/6, 2010 at 15:50 Comment(11)
Yeah I guess I thought scheme and authority were always mutually dependent. It makes sense that it's not, but it's not something I've encountered until very recently.Ocana
It is not guaranteed to work in any browser. It is guaranteed to work only in browsers that follow the RFC.Cellaret
@Roger Pate: I have yet to see a browser not follow the RFC for URI. That particular standard has been around for so long... I've just tested it in IE3.0 and it understands it perfectly fine. If you fall on a browser that doesn't understand those links, chances are it is such a marginal browser that it won't matter.Idem
@Andrew: Maybe you differ from me, but when I say "guarantee" in the context of programming, I really mean "there is no way this can possibly, ever fail," not just "it only works in popular implementations that I've tested." I didn't mean to make a big deal out of it, but it seemed important enough to mention.Cellaret
@Roger: Yes, but in the context of web development, marginal browsers (<0.01% market share) are not taken into consideration. It's like saying that an API is present in all versions of Windows and then someone comes it to say that it might not be supported in Wine...Idem
@Kugel: Yes, Python is readable. :) -- @Andrew: Marginal browsers like IE7&8? SLaks points out how they have problems using these URLs, which is the type of nuance hidden by "guaranteed to work" in a technical context. All you have to say is "RFC 3986 requires this behavior, which all mainstream browsers handle," but that's already said on the duplicate anyway.Cellaret
@Roger Pate: Loading a CSS file twice doesn't break a site. It's a minor inconvenience that technical users won't notice anyway. And you should know that nothing is guaranteed in IT anyway. There are always edge cases.Idem
Great diagram there. Given that diagram I wonder in what way src="//youtube.com" is different from src="youtube.com"? Why would you use the former instead of the latter in any case? Does it matter at all or are they semantically identically?Ephod
@SteveMidgley: youtube.com points to a file/directory called "youtube.com" relative to the current URL. //youtube.com points to the domain "youtube.com" on the same scheme the current URL is using. They are not the same at all.Idem
Thanks @Andrew Moore. Brainfreeze on my end. Thinking of browsers which sub the protocol in when you type the URL! Duh. For src="... obviously you have to specify the protocol so // is a very useful nomenclature.Ephod
Awesome graph showing the parts of the URI. Very concise in explanationSentimentality
S
82

are there any cases where it doesn't work?

If the parent page was loaded from file://, then it probably does not work (it will try to get file://cdn.example.com/js_file.js, which of course you could provide locally as well).

Shuttlecock answered 19/10, 2011 at 8:27 Comment(5)
A must know for guys testing html on local machine!Rawlins
argh... no wonder my script src="//..." wasn't working! I was opening the html file locally!Floret
Anyone know a way around this?Elayneelazaro
@ogc-nick: You can run a local web server. Plenty options these days, with zero configuration. You want that anyway, as many other things (such as XHR or web workers also don't work for the file: domain)Shuttlecock
@Shuttlecock That has been working temporarily for me but I am making an app with Github's Electron and that gets a bit more complicated.Elayneelazaro
W
41

Many people call this a Protocol Relative URL.

It causes a double-download of CSS files in IE 7 & 8.

Worthen answered 4/6, 2010 at 15:49 Comment(1)
@AndrewMoore As the "thing" being excluded indicates the web protocol, calling it "protocol relative" makes more sense. I've never heard of ftp or http being called "schemes"...Burberry
T
27

Here I duplicate the answer in Hidden features of HTML:

Using a protocol-independent absolute path:

<img src="//domain.com/img/logo.png"/>

If the browser is viewing an page in SSL through HTTPS, then it'll request that asset with the https protocol, otherwise it'll request it with HTTP.

This prevents that awful "This Page Contains Both Secure and Non-Secure Items" error message in IE, keeping all your asset requests within the same protocol.

Caveat: When used on a <link> or @import for a stylesheet, IE7 and IE8 download the file twice. All other uses, however, are just fine.

Tired answered 15/2, 2009 at 0:15 Comment(0)
B
17

It is perfectly valid to leave off the protocol. The URL spec has been very clear about this for years, and I've yet to find a browser that doesn't understand it. I don't know why this technique isn't better known; it's the perfect solution to the thorny problem of crossing HTTP/HTTPS boundaries. More here: Http-https transitions and relative URLs

Barneybarnhart answered 15/2, 2009 at 2:2 Comment(0)
E
10

are there any cases where it doesn't work?

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>

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][3].

Existentialism answered 3/6, 2016 at 8:20 Comment(0)
B
7

1. Summary

Answer for 2019: you can still use protocol-relative URLs, but this technique an anti-pattern.

Also:

  1. You may have problems in developing.
  2. Some third-party tools may not support them.

Migrating from protocol-relative URLs to https:// it would be nice.


2. Relevance

This answer is relevant for January 2019. In the future, the data of this answer may be obsolete.


3. Anti-pattern

3.1. Argumentation

Paul Irish — front-end engineer and a developer advocate for the Google Chromewrite in 2014, December:

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.

Allowing the snippet to request over HTTP opens the door for attacks like the recent GitHub Man-on-the-side attack. It’s always safe to request HTTPS assets even if your site is on HTTP, however the reverse is not true.

3.2. Another links

3.3. Examples


4. Developing process

For example, I try to use clean-console.

  • Example file KiraCleanConsole__cdn_links_demo.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>clean-console without protocol demonstration</title>
    <!-- Really dead link -->
    <script src="https://unpkg.com/bowser@latest/bowser.min.js"></script>
    <!-- Package exists; link without “https:” -->
    <script src="//cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
    <!-- Package exists: link with “https:” -->
    <script src="https://cdn.jsdelivr.net/npm/gemini-scrollbar/index.js"></script>
</head>
<body>
    Kira Goddess!
</body>
</html>
  • output:
D:\SashaDebugging>clean-console -i KiraCleanConsole__cdn_links_demo.html
checking KiraCleanConsole__cdn_links_demo.html
phantomjs: opening page KiraCleanConsole__cdn_links_demo.html

phantomjs: Unable to load resource (#3URL:file://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js)


phantomjs:   phantomjs://code/runner.js:30 in onResourceError
Error code: 203. Description: Error opening //cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js: The network path was not found.

  phantomjs://code/runner.js:31 in onResourceError

phantomjs: Unable to load resource (#5URL:https://unpkg.com/[email protected]/bowser.min.js)


phantomjs:   phantomjs://code/runner.js:30 in onResourceError
Error code: 203. Description: Error downloading https://unpkg.com/[email protected]/bowser.min.js - server replied: Not Found

  phantomjs://code/runner.js:31 in onResourceError

phantomjs: Checking errors after sleeping for 1000ms
2 error(s) on KiraCleanConsole__cdn_links_demo.html

phantomjs process exited with code 2

Link //cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js is valid, but I getting an error.

Pay attention to file://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js and read Thilo and bg17aw answers about file://.

I didn't know about this behavior and couldn't understand why I have problems like this for pageres.


5. Third-party tools

I use Clickable URLs Sublime Text package. Use it, I can simply open links from my text editor in browser.

CSS links examples

Both links in example are valid. But first link I can successfully open in browser use Clickable URLs, second link — no. This may not be very convenient.


6. Conclusion

Yes:

  1. If you have problems as in Developing process item, you can set your development workflow.
  2. Else you have problems as in Third-party tools item, you can contribute tools.

But you don't need this additional problems. Read information by links in Anti-pattern item: protocol-relative URLs is obsolete.

Birchard answered 27/1, 2019 at 10:0 Comment(0)
R
4

Following the gnud's reference, the RFC 3986 section 5.2 says:

If the scheme component is defined, indicating that the reference starts with a scheme name, then the reference is interpreted as an absolute URI and we are done. Otherwise, the reference URI's scheme is inherited from the base URI's scheme component.

So // is correct :-)

Richrichara answered 13/4, 2012 at 8:17 Comment(0)
I
3

Yes, this is documented in RFC 3986, section 5.2:

(edit: Oops, my RFC reference was outdated).

Incorrigible answered 4/6, 2010 at 15:49 Comment(0)
S
3

It is indeed correct, as other answers have stated. You should note though, that some web crawlers will set off 404s for these by requesting them on your server as if a local URL. (They disregard the double slash and treat it as a single slash).

You may want to set up a rule on your webserver to catch these and redirect them.

For example, with Nginx, you'd add something like:

location ~* /(?<redirect_domain>((([a-z]|[0-9]|\-)+)\.)+([a-z])+)/(?<redirect_path>.*) {
  return 301 $scheme:/$redirect_domain/$redirect_path;
}

Do note though, that if you use periods in your URIs, you'll need to increase the specificity or it will end up redirecting those pages to nonexistent domains.

Also, this is a rather massive regex to be running for each query -- in my opinion, it's worth punishing non-compliant browsers with 404s over a (slight) performance hit on the majority of compliant browsers.

Smoothen answered 3/9, 2013 at 10:28 Comment(0)
I
3

We are seeing 404 errors in our logs when using //somedomain.com as references to JS files.

The references that cause the 404s come out looking like this: ref:

<script src="//somedomain.com/somescript.js" />

404 request:

http://mydomain.com//somedomain.com/somescript.js

With these showing up regularly in our web server logs, it is safe to say that: All browsers and Bots DO NOT honor RFC 3986 section 4.2. The safest bet is to include the protocol whenever possible.

Immolation answered 29/5, 2014 at 14:19 Comment(2)
Yeah, I've kinda of switched away from it, but not because of 404s (I've never seen any 404s...if a bot doesn't honour it, I could care less) – because I no longer load resources from other CDNs so I don't have a need to do this (instead I minify as much as possible into 1 or 2 files).Elodiaelodie
Please include the protocol. Protocol-less refs break in my Cordova app.Dedie
H
2

The pattern I see on html5-boilerplate is:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.10.2.min.js"><\/script>')</script>

It runs smoothly on different schemes like http, https, file.

Hodgkin answered 21/11, 2013 at 19:11 Comment(5)
This is no longer true, see https://mcmap.net/q/18719/-is-it-valid-to-replace-http-with-in-a-lt-script-src-quot-http-quot-gt or here, they now use https:// for everythingExistentialism
@Existentialism The problem with using https:// everywhere is that you then have to keep checking all your external links to see if they actually support it, and change them to http:// if they do not (as otherwise they will not work). This may be troublesome with a large number of links.Vowelize
@Vowelize you are missing the point, I was only reffering to the particular case of linking to content from CDNs. https:// is mandatory for that nowadays. The answer also talks about a particular case (html5-boilerplate). There is no "checking for http" as you say, as CDNs always use https now.Existentialism
@Existentialism That is true but the general question here is not only about CDNs. By reading just this answer/comment it is easy to think that https:// should (or can) be used in all links which is not correct.Vowelize
@Vowelize The beauty of having multiple answers is that while none of them is perfect (if an answer would be perfect, the others would need to be deleted), reading a few of them gives us a broader view. In this case, the answer says "the pattern on html5boilerplate is..." and my comment updates this answer mentioning "that is no longer the pattern on html5-boilerplate". That's it. A needed addition to this particular answer. Also please note the original question is indeed about CDNs!Existentialism
E
1

As your example is linking to an external domain, if you are using HTTPS then you should verify that the external domain is setup for SSL as well. Otherwise, your users may see SSL errors and/or 404 errors (e.g. older versions of Plesk store HTTP and HTTPS in separate folders). For CDNs, it shouldn't be an issue but for any other website it could be.

On a side note, tested while updated an old website and also works in the url= part of a META REFRESH.

Eglanteen answered 25/4, 2018 at 23:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.