Stylus / Nib CSS with Node / Express secure app triggers Chrome warnings about insecure JavaScript - css

Console messages:
The page at [...] ran insecure content from http://fonts.googleapis.com/css?family=Quicksand.
and
The page at [...] displayed insecure content from http://themes.googleusercontent.com/static/fonts/quicksand/v2/sKd0EMYPAh5PYCRKSryvWz8E0i7KZn-EPnyo3HZu7kw.woff.
and
Resource interpreted as Font but transferred with MIME type font/woff: "http://themes.googleusercontent.com/static/fonts/quicksand/v2/sKd0EMYPAh5PYCRKSryvWz8E0i7KZn-EPnyo3HZu7kw.woff".
I know what caused it--vaguely. I just started implementing Stylus, Nib CSS modules.

In my Google research I found: http://mccormicky.com/1595/importing-google-web-fonts-lightspeed-web-store-ssl/
which makes it clear that the font requests should be switched to https for the whole thing to be considered secure, so then I looked into my /public/styles/style.styl file and found the offending line. One extra s should be sufficient to clear the warning. Indeed it's fine now.
It's really as simple as making the font request (found in the CSS styles file) over https instead of http.
I hadn't intended to be answering my own question (really thought the fix would be something complicated with the headers), but by the time I'd half finished it and done my due diligent research it was answerable. So, whatever.

Related

IE9 redirect caching, fonts, and cross domain resource sharing(CORS) CDN HTTP headers

I thought I have somehow found a solution to the very vexing problem with Firefox and CDN-hosted fonts access, but here comes IE9.
I recently found a very frustrating issue with IE9 caching problem, and chanced upon this blog post (IE9 Redirect Caching Nightmare) which enlightened me more about the actual issue.
I have to admit that I'm not sure whether the above mentioned is actually the issue, but it seems close enough.
Problem:
I have a website set up with 2 domains(base domain and subdomain) pointing to the same server, serving the exact same website which is using a same set of resources from a CDN hosted on Amazon S3, served by Cloudfront.
https://example.com
https://www.example.com
I get these kind of error messages in my IE9 developer tools console when loading fonts from my CSS file using #font-face:
CSS3117: #font-face failed cross-origin request. Resource access is restricted.
This happens when I loaded either of the URL first, then visiting the other second. IE9 is not running in Compatibility Mode. It running is in Document Mode: IE9 Standards.
From my limited understanding of the CORS and the need to set Access-Control-Allow-Origin HTTP header, I have dutifully set it up in S3 CORS policy, and it works perfectly fine with Firefox.
Requests from both domains, will get their respective header when requesting the CDN resource.
It seems that IE9 tried to do some optimization with caching, and cached the redirect too.
This causes a problem as the Access-Control-Allow-Origin header is cached as well. Without sending a request to the CDN server, the Access-Control-Allow-Origin header cannot change for different domains.
So I'm left with a situation where the request is from https://www.example.com and yet the Access-Control-Allow-Origin is https://example.com. This leads to the restricted resource problem with the error message above.
Further look: I did a check with Firefox 19, the above situation actually occurs, but it does not encounter the same strict restriction as IE9. Subdomain (https://www.example.com) requesting information will accept the access-control-allow-origin of the main domain(https://example.com). Chrome (Webkit) doesn't seem to care. I'm at a loss about which browser's behaviour implementation is correct.
With my current settings in the CDN, it seems like Chrome and Firefox, automatically reroutes allwww subdomain requests to the main domain. Only upon multiple attempts of inputing the www subdomain in the address bar, then will Chrome and Firefox obey. IE9 on the other hand, just goes to whichever address is typed in the address bar. IE9 seems to be the odd one out here, but I'm not sure which browser's behaviour is actually correct.
From a usability standpoint, Chrome and Firefox seems to be the "correct" behaviour.
Known Possible Solutions:
Set Access-Control-Allow-Origin header to allow all, i.e. *
Turn off caching in the browser
Redirect one domain to the other
Use query string to differentiate different domain calls for resource
Embed the font into the CSS as data-uri
For solution 1, let's just say I'm paranoid that I just want to set specific domains to allow.
For solution 2, is not optimal if I were to set it for all browsers, also my site has to run on mobile devices with usually less-than-desirable download speeds.
For solution 3, possible, but I'm still curious for solution to deal directly with the IE9 caching issue.
For solution 4, it is very hard to implement especially when the resource is called from #font-face. Does it mean that I'll have to dynamically re-generate the CSS for different domain calls for the different line just to load a font to bypass the issue? Seems to defeat the purpose of CSS itself, and caching resources for that matter.
edit: Stylesheet works, font-loading doesn't.
For Solution 5, it is tedious for maintenance and updating, especially when there are changes to the font files periodically.
Question: Are there any known ways to deal specifically with IE9's redirect caching behaviour in this particular case?
Answers and comments are very much appreciated. Thanks in advance!
Edit: More browser test information.
Solution 1:
Check this question.
Solution 4: rename your CSS file to style.php and use whatever code you need to call the appropriate resource.
Set the content type at the top of the page.
<?php
header("Content-type: text/css; charset: UTF-8");
?>
More info about style.php from Chris Coyier.
We discovered the same weird behavior also in IE10 and IE11.
Resetting the browser cache makes the fonts to be loaded without any problem. Also enabling and disabling compatibility mode.
But when switching to another subdomain, IE does not render the font because request header does not match the response header which is still the URL of the last request. And IE always shows the full URL for even if the definition on the bucket is *.ourdomain.com
So the general issue with allowing cross origin requests to assets like webfonts was solved by adding CORS permissions to the S3 Bucket - that made the webfonts work perfectly in Firefox.
But we still have no idea how to avoid * and tell IE not to cache the response headers.

cache busters and cross-browser concerns

My code to load JavaScript file is:
<script src="/path/to/app.js?1350550684711"></script>
where 1350550684711 is just a server-side generated timestamp. This practice of cache busting is quite popular (link 1, link 2).
In Chrome and Firefox this mechanism works, and in theory it should work for all browsers, since a different HTTP resource is being requested every time.
Still reports are coming in of users using cached versions of the JS file; specifically those on Apple Safari. Any idea?
That could mean that the affected Apple Safaris reuse a cached version of the html page that contains the <script elements, and thus naturally they would not get a new timestamp from the server.
I'm speculating here, but that could be because they interpret the HTTP cache related headers differently, potentially due to differing default settings, offline browsing mode or whatever.
Check which cache settings apply to that html file.

Javascript not downloading fully

Ok, this might be more of a networking question than programming but I'm not really sure what is going on here:
I'm having intermittent problems with my site where I am only partially downloading javascript documents. By intermittent, I mean that on the same browser (Safari in this case) I can view that javascript file in my browser and refresh the page and still only see the file partially downloaded, but another browser (Chrome) I see the file correctly downloaded. Clearing the browser cache has no effect either.
The odd thing is that it appears to be location specific, as when I check the site from home, still using Safari, I have zero issues. The problem also seems to be machine independent, as I also occasionally get the same javascript errors on my iPad (when at work on the same network).
I'm 100% sure it isn't a syntax error or anything with the javascript, as the file that fails most often is a minified copy of jQuery (downloaded from their site, though hosted on my site's server)
I have tried turning off mod_deflate on the idea that it might be compression that was causing the issue, but this had no effect.
I have spoken to the network admins at both my end, and the hosting server end and they claim that it isn't anything wrong with their network, though they are possibly just deflecting a complex issue.
Any ideas on how I can narrow down the issue?

How to determine what in the new FB App iframe browser is breaking https in my App

https://www.facebook.com/apps/application.php?id=212108875466071
As far as I can tell, we are doing everything right, and FB's new new mini-feed App browser seems to be injecting ONE or TWO insecure resources from time to time.... NOT all the time.
How can I be positive it's FB's fault, so I can file a bug? We are only showing broken https with the new iframe.... and most of what is being is supplied by that setup IS secure, but they have stupid little things like an insecure 'credits' ikon, which breaks the whole damn thing.
If it's our fault, I need to fix it. If it's FB's, I need to stop wasting so much time debugging their platform for them.
Look at chrome's javascript console, it show warnings when an insecure resource is loaded on a secure page.
See the warning before the syntax error.
See also http://googleonlinesecurity.blogspot.com/2011/06/trying-to-end-mixed-scripting.html (where this image come from).

Can I change all my http:// links to just //?

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?
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:
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.
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).
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.
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.
Yes, network-path references were already specified in RFC 1808 and should work with all browsers.
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.
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
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.

Resources