Skip to content

Instantly share code, notes, and snippets.

@subzey
Last active October 28, 2020 17:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save subzey/78af9791b469389d934e54eca9d42bda to your computer and use it in GitHub Desktop.
Save subzey/78af9791b469389d934e54eca9d42bda to your computer and use it in GitHub Desktop.
cache-control
#!/usr/bin/env node
import { createServer } from 'http';
import { readFile } from 'fs/promises';
import { resolve } from 'path';
import { parse, fileURLToPath } from 'url';
const ALIGNMENT = 60000; // ms
const TTL = 80000; // ms
function promisleep(delay){
return new Promise(r => setTimeout(r, delay))
}
async function serveIndex(req, res) {
const fileContents = await readFile(resolve(fileURLToPath(import.meta.url), '..', 'index.html'));
res.writeHead(200, {
'content-type': 'text/html;charset=utf-8',
'content-length': fileContents.byteLength,
});
res.end(fileContents);
}
async function serveToken(req, res) {
console.log(`${new Date().toISOString()} Token request...`);
await promisleep(1000);
const now = Date.now(); // ms
const iat = Math.floor(now / ALIGNMENT) * ALIGNMENT; // ms
const exp = iat + TTL; // ms
const age = now - iat; // ms
const headers = {
'content-type': 'application/json;charset=utf-8',
'age': Math.round((now - iat) / 1000),
'cache-control': `private, max-age=${ ALIGNMENT / 1000 }, stale-while-revalidate=${ (TTL - ALIGNMENT) / 1000 }`,
};
res.writeHead(200, headers);
res.end(
JSON.stringify({
iat: new Date(iat).toISOString(),
exp: new Date(exp).toISOString(),
})
);
console.log(`${new Date().toISOString()} ${JSON.stringify(headers, null, 2)}`);
}
(
createServer((req, res) => {
switch (parse(req.url).pathname) {
case '/':
return serveIndex(req, res);
case '/get-token/':
return serveToken(req, res);
default:
res.writeHead(404);
res.end();
}
})
.on('listening', function() { console.log(`http://127.0.0.1:${this.address().port}/`)})
.listen(8080)
);
<!doctype html>
<html>
<head>
<style>pre { margin: 1em; border: 1px dashed gray; min-height: 100px }</style>
</head>
<body>
<button id="fetch">Fetch!</button>
<pre id="output"><div id="now"></div><div id="response"></div></pre>
<script>
document.querySelector('#fetch').addEventListener('click', async (e) => {
e.preventDefault();
const output = document.querySelector('#response');
try {
const response = await fetch('/get-token/');
if (!response.ok) {
throw new Error(`Pas glop! ${response.status}`);
}
const json = await response.json();
const serverDate = new Date(response.headers.get('date')).toISOString();
const localDate = new Date().toISOString();
output.textContent = `\nLocal time:\t${localDate}\nServer time:\t${serverDate}\n\nIssued at:\t${json.iat}\nExpires at:\t${json.exp}`;
} catch (e) {
output.textContent = `Error: ${e.stack || e.message}`;
}
});
requestAnimationFrame(function frame(){
document.querySelector('#now').textContent = new Date().toISOString();
requestAnimationFrame(frame);
});
</script>
</body>
</html>
{
"type": "module",
"name": "token-cache",
"version": "0.1.0",
"bin": "cli.js"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment