80

I am adding an external CSS file and an external JS file to my headers and footers. When loading an HTTPS page, some browsers complain that I am loading unsecured content.

Is there an easy way to make the browser load the external content via HTTPS when the page itself is HTTPS?

Nathan H
  • 44,105
  • 54
  • 154
  • 235

4 Answers4

126

Use protocol-relative paths.

Thus not

<link rel="stylesheet" href="http://example.com/style.css">
<script src="http://example.com/script.js"></script>

but so

<link rel="stylesheet" href="//example.com/style.css">
<script src="//example.com/script.js"></script>

then it will use the protocol of the parent page.

BalusC
  • 992,635
  • 352
  • 3,478
  • 3,452
  • 4
    That's a browser-specific problem. There are no other ways to solve this the robust way than doing this entirely at the server side using the capabilities of the view technology in question. – BalusC Apr 27 '10 at 22:31
  • 1
    As an additional note, if you take care about the [right caching entries](http://stackoverflow.com/questions/49547/making-sure-a-web-page-is-not-cached-across-all-browsers/2068407#2068407) in the response headers, the browsers won't download it on the subsequent requests until the expire is reached, including IE. – BalusC Apr 27 '10 at 22:41
  • I would say just always use `https://` resources when available. They will load just fine in your page, regardless of scheme – Phil Jul 12 '18 at 05:44
  • @Phil: not if the target environment doesn't support HTTPS, usually during development at localhost. – BalusC Jul 12 '18 at 15:43
  • @BalusC _"... when available... "_ – Phil Jul 12 '18 at 21:39
7

nute & James Westgate are right when comenting on the later answer.

If we take a look at miscelanous industry-grade external javascript includes, the successfull ones use both document.location.protocol sniffing and script element injection tu use the proper protocol.

So you could use something like :

<script type="text/javascript">
  var protocol = (
      ("https:" == document.location.protocol) 
      ? "https" 
      : "http"
  );
  document.write(
      unescape(
          "%3Cscript"
              + " src='"
                  + protocol 
                  + "://"
                  + "your.domain.tld"
                  + "/your/script.js"
              + "'"
              + " type='text/javascript'
          + "%3E"
          + "%3C/script%3E"
      ) // this HAS to be escaped, otherwise it would 
        // close the actual (not injected) <script> element
  );
</script>

The same can be done for external CSS includes.

And by the way: be careful to only use relative url() path in your CSS, if any, otherwise you might still get the "mixed secure and unsecure" warning....

Alain BECKER
  • 710
  • 5
  • 13
  • This is just something you have to consider when deciding which technology to use. If you cannot do this on the server side, and you need to go across hosts, then you have no other option. – Geoff Apr 27 '10 at 22:58
1

If you use relative paths ( and the content is on the same domain) then the content should use whichever protocol the page was requested in.

However if you are going across domain to a CDN or resource site, or if you need to use absolute paths, then you will need to use server side script to change the links, or always use https://

James Westgate
  • 10,385
  • 6
  • 56
  • 63
  • We are going across domain. Would using javascript to write the include work? If document.location.protocol then ... – Nathan H Apr 27 '10 at 22:19
  • Trying using js by inserting markup into the HEAD tag, perhaps a simple document.write inside a script tag .. – James Westgate Apr 27 '10 at 22:24
  • 1
    This is approach taken by Google Analytics code, it simply does a document.write with the protocol of the containing page. – Geoff Apr 27 '10 at 22:57
  • "you will need to use server side script" - why? Caching? XSS concerns? Browsers? – mlhDev Oct 02 '12 at 12:55
  • This seems like I meant protocol relativ paths when I answered the question, but I cant be sure. I know IE8 and below has a caching issue with protocol relative paths that should be checked. I wouldn't write each resource out using script if you are keen on performance, it can trigger all sorts of async and blocking issues. – James Westgate Oct 08 '12 at 13:19
0

In contradiction to the escaped response (which will also work) you could skip that part and use the correct way to add nodes to your dom tree:

<script type="text/javascript" language="javascript">
    var fileref=document.createElement('script');
    fileref.setAttribute("type","text/javascript");
    fileref.setAttribute("src", document.location.protocol + '//www.mydomain.com/script.js');
    document.getElementsByTagName("head")[0].appendChild(fileref);
</script>

But the protocol-relative path would be the way to go.

gkempkens
  • 395
  • 3
  • 12