4

This might be a stupid question, but I'll take my chances.

On my site, I include the following script file:

<script src="http://connect.facebook.net/en_US/all.js"></script>

Normally, this would work just fine. However, where I work we have a firewall that blocks any traffic to the facebook.com or facebook.net domains as obviously no employee has enough self-control to prevent themselves from playing Farmville all day long instead of working.

Thus, when the script loads it actually gets a bunch of HTML saying the site is blocked. Since this is HTML and not valid Javascript, the browser pops up script errors. Note, I still get an HTTP 200 so I can't catch errors that way.

I'm willing to accept this is an edge case, since only a small percentage of users would be trying to access my site from behind a firewall that happens to block Facebook traffic, but I still find myself wondering if there's something relatively easy I can do to test to make sure the link returns valid Javascript, or perhaps surround the loading of the script in a giant try/catch block and handle errors gracefully. Any ideas would be much appreciated!

UPDATE:

Here's the HTTP headers from the firewall's error page. Perhaps I can look at the "content-type" header, which I assume would be text/javascript if the content was valid.

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: text/html; charset=utf-8
Proxy-Connection: Keep-Alive
Connection: Keep-Alive
Content-Length: 4774
Mike Christensen
  • 88,082
  • 50
  • 208
  • 326
  • Could you fetch the script with an AJAX "GET" request and make sure it doesn't start with HTML markup? – Pointy Feb 02 '12 at 16:38
  • or maybe you can check if some response headers are overwritten with some firewall settings – Fabrizio Calderan Feb 02 '12 at 16:41
  • Is the response length always of 4774 bytes when this resource is blocked? what's the content of the response? – Fabrizio Calderan Feb 02 '12 at 16:51
  • @FabrizioCalderan - Yea, you might be on to something since the Content-Type would be different if the response was HTML. I suppose one way would be to do a test load of the file with AJAX, look at the Content-Type, then insert the script tag into the DOM (ideally, this would only download the file once as it would be cached).. Or maybe I could issue an HTTP HEAD command first. – Mike Christensen Feb 02 '12 at 16:53
  • @FabrizioCalderan - The content of the response is a company specific "This site is blocked" error message. It would always be 4774 bytes for us, but would of course be different depending on how your firewall handled these violations. – Mike Christensen Feb 02 '12 at 16:54

3 Answers3

1

This is how a fallback is done:

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

In this case, it attempts to load jquery from googleapis.com. If that is blocked or unavailable it loads a local jQuery.

You can use the same technique. Make a second script to detect if the facebook script file has loaded. If it has not loaded then don't run any associated script with it.

Simon Sarris
  • 62,212
  • 13
  • 141
  • 171
  • I think that the first script inclusion generates errors anyway (if I well understood) – Fabrizio Calderan Feb 02 '12 at 16:42
  • Agreed - It's a great way to fallback and load the script from elsewhere, but it'll still popup with syntax errors. – Mike Christensen Feb 02 '12 at 16:47
  • I think if not specified the protocol in src of script tag, can cause problems in navigators that default protocol is not http. – Jack Feb 02 '12 at 16:56
  • @Jack: No, schemaless or protocol-relative URLs [are just fine](http://stackoverflow.com/a/4832046/201952). The only thing to watch out for is some IE quirks loading stylesheets from a schemaless URL. – josh3736 Feb 02 '12 at 17:14
  • You could just use `<\/script>` instead of `\x3C/script>`. See http://mths.be/etago. – Mathias Bynens Feb 02 '12 at 17:39
1

Looking at your edit, you could check via ajax the content type of the response and when it's text/html don't append the script: use <xhr>.getResponseHeader("Content-Type");

Edit: As josh3736 pointed out, Cross-site request are not allowed via javascript so you will also need to call an internal resource (written in a server side language) that works as a proxy and try to get the script, returning its content type (e.g. look at this discussion: php, curl, headers and content-type)

Community
  • 1
  • 1
Fabrizio Calderan
  • 120,726
  • 26
  • 164
  • 177
  • I'll run with this and see if I can get something working. I'm using the YUI2 framework, which has various utilities for this sort of thing. – Mike Christensen Feb 02 '12 at 16:57
  • getResponseHeader() is a javascript method of xmlHttpRequest Object. So having your *xhr* object you can use it everywhere, no matter what your library is – Fabrizio Calderan Feb 02 '12 at 17:00
  • This will not work. XHR does not allow cross-Origin requests. – josh3736 Feb 02 '12 at 17:10
  • @josh3736 right, he will need a proxy written in some server side language (e.g. Using CURL) that returns the content type – Fabrizio Calderan Feb 02 '12 at 17:32
  • @FabrizioCalderan: Except that his server is outside the offending firewall, so it will always say "ok!" This is a client problem. – josh3736 Feb 02 '12 at 17:38
1

Unfortunately, there's no way for you to test that connect.facebook.net is not being blocked since it is served from a different Origin than your document.

This means you can't use XHR to issue a HEAD request and make sure the content type is really text/javascript – XHR won't make a cross-Origin request by default, and connect.facebook.net doesn't support CORS:

OPTIONS http://connect.facebook.net/en_US/all.js HTTP/1.1
Host: connect.facebook.net
Access-Control-Request-Method: GET
Access-Control-Request-Headers: Origin, X-Requested-With, Accept

HTTP/1.1 501 Not Implemented
Server: AkamaiGHost
Mime-Version: 1.0
Content-Type: text/html
Content-Length: 272
Connection: close

Technically speaking, the filtering/firewall software in question is incorrect in that when it blocks a site, it provides a success status code (200) when it should be providing an error code (4xx or 5xx). If it did correctly respond with an error condition, the browswer wouldn't parse the response body as script (thus causing errors).

Community
  • 1
  • 1
josh3736
  • 139,160
  • 33
  • 216
  • 263