Last active
January 2, 2017 15:23
-
-
Save rankun203/1b0069a7005b22552fd3e24a2493e881 to your computer and use it in GitHub Desktop.
Use service worker to quickly fail non accessible URLs.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Service Worker test</title> | |
<script> | |
navigator.serviceWorker.getRegistration().then(function (registration) { | |
if (!registration || !navigator.serviceWorker.controller) { | |
navigator.serviceWorker.register('./sw.js').then(function () { | |
console.log('Service worker registered, reloading the page'); | |
window.location.reload(); | |
}); | |
} else { | |
console.log('DEBUG: client is under the control of service worker'); | |
} | |
}); | |
</script> | |
<link rel='stylesheet' id='extra-fonts-css' | |
href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800&subset=latin,latin-ext' | |
type='text/css' media='all'/> | |
</head> | |
<body> | |
<script src="https://lodestreams-com.disqus.com/count.js?check-china=true"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** Indicates that current user is browsing from China. */ | |
ServiceWorkerGlobalScope.inChina = null; | |
var DEBUG = true; | |
var EMPTY_RESPONSE = ''; | |
/** The patterns to be checked against the requesting URL. */ | |
var CHECK_CHINA_PATTERNS = [ | |
'check-china=true', | |
'disqus.com', | |
'googleapis.com' | |
]; | |
/** | |
* Clear inChina global var. | |
* User may request through a proxy sometime, so it's better to just | |
* clear the inChina var in nearly future. | |
* | |
* @param sec {Number} Seconds later to take the action. Default is 2 minutes. | |
*/ | |
function clearInChinaVarLater(sec) { | |
clearTimeout(ServiceWorkerGlobalScope.clearInChinaVarLater_TIMER); | |
ServiceWorkerGlobalScope.clearInChinaVarLater_TIMER = setTimeout(function () { | |
console.log('ServiceWorkerGlobalScope.inChina = undefined'); | |
ServiceWorkerGlobalScope.inChina = undefined; | |
}, sec || 2 * 60 * 1000); | |
} | |
/** | |
* Fetch resource with China detection. | |
* If in China, returns Empty response, otherwise returns a real request response. | |
* This function will also cache the inChina as a service worker level global variable, and will clear it later. | |
* @param theRequest {Request} The requesting Request, needed for firing another real request (event.request). | |
* @returns {Response|Promise} response if it's a empty response, Promise if it's requesting the real URL. | |
*/ | |
function fetchWithChinaDetection(theRequest) { | |
clearInChinaVarLater(); | |
if (ServiceWorkerGlobalScope.inChina === false) { | |
return fetch(theRequest); | |
} | |
if (ServiceWorkerGlobalScope.inChina === true) { | |
return new Response(EMPTY_RESPONSE); | |
} | |
return fetch('https://freegeoip.net/json/') | |
.then(function (resp) { | |
return resp.json() | |
}) | |
.then(function (json) { | |
var country = json && json.country_code; | |
if (country && country.indexOf('CN') >= 0) { | |
if (DEBUG) console.log('ServiceWorkerGlobalScope.inChina === true'); | |
ServiceWorkerGlobalScope.inChina = true; | |
return new Response(EMPTY_RESPONSE); | |
} | |
if (DEBUG) console.log('ServiceWorkerGlobalScope.inChina === false'); | |
ServiceWorkerGlobalScope.inChina = false; | |
return fetch(theRequest); | |
}); | |
} | |
/** | |
* Entrance event. | |
* If current request is considered not accessible in China, | |
* check current user location before make the decision. | |
* | |
* Otherwise, for normal requests, just return their originals. | |
* @param event {Event} The request Event, event.request is a Request. | |
*/ | |
self.onfetch = function (event) { | |
var checkChina = false; | |
CHECK_CHINA_PATTERNS.forEach(function (p) { | |
checkChina = checkChina || event.request.url.indexOf(p) >= 0; | |
}); | |
if (checkChina) { | |
if (DEBUG) console.log('checkChina is true for ' + event.request.url); | |
return event.respondWith(fetchWithChinaDetection(event.request)); | |
} | |
return event.respondWith(fetch(event.request)); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment