Skip to content

Instantly share code, notes, and snippets.

@wesbos
Created February 20, 2025 20:55
Show Gist options
  • Save wesbos/1d8c27777c131cf408915872bc68f47d to your computer and use it in GitHub Desktop.
Save wesbos/1d8c27777c131cf408915872bc68f47d to your computer and use it in GitHub Desktop.
const http = require('http');
const MAX_AGE = 5; // seconds
const STALE_WHILE_REVALIDATE = 200; // seconds
const server = http.createServer((req, res) => {
// Set cache control headers
res.setHeader('Cache-Control', `max-age=${MAX_AGE}, stale-while-revalidate=${STALE_WHILE_REVALIDATE}`);
// Get current time
const now = new Date();
const currentTime = now.toLocaleTimeString();
const currentTimestamp = Date.now();
console.log(`Generating a new Response!`, currentTime);
// Send HTML response
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="icon" href="https://fav.farm/🔥" />
<meta charset="UTF-8">
<title>Time Server</title>
<style>
body {
font-family: system-ui, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 2rem;
line-height: 1.5;
}
.time {
font-size: 2rem;
font-weight: bold;
margin: 1rem 0;
}
.elapsed {
color: #666;
}
.cached {
background: #ffd70033;
padding: 1rem;
border-radius: 4px;
margin: 1rem 0;
}
.status {
padding: 0.5rem 1rem;
border-radius: 4px;
display: inline-block;
margin: 1rem 0;
}
.status.fresh {
background: #d4edda;
color: #155724;
}
.status.stale {
background: #fff3cd;
color: #856404;
}
.refresh-link {
display: inline-block;
padding: 0.5rem 1rem;
background: #007bff;
color: white;
text-decoration: none;
border-radius: 4px;
margin: 1rem 0;
}
.refresh-link:hover {
background: #0056b3;
}
.refresh-status {
margin: 1rem 0;
font-style: italic;
}
</style>
</head>
<body>
<h1>Time Server</h1>
<div id="status"></div>
<div class="time">Server time: <span id="serverTime">${currentTime}</span></div>
<div class="elapsed">Time elapsed since server generated this response: <span id="elapsedTime">0</span> seconds</div>
<div id="refreshStatus" class="refresh-status"></div>
<a href="/" class="refresh-link">↻ Refresh Page</a>
<div class="cached">
<strong>How this works:</strong>
<ul>
<li>This response can be cached for ${MAX_AGE} seconds (max-age=${MAX_AGE})</li>
<li>After ${MAX_AGE} seconds, it can serve stale content for up to ${STALE_WHILE_REVALIDATE} seconds while revalidating</li>
<li>The elapsed time shows how old this response is - if it's more than ${MAX_AGE} seconds, you're seeing a stale response!</li>
</ul>
</div>
<script>
const serverTimestamp = ${currentTimestamp};
const maxAge = ${MAX_AGE};
const elapsedTime = document.getElementById('elapsedTime');
const status = document.getElementById('status');
const refreshStatus = document.getElementById('refreshStatus');
// Calculate initial elapsed time and set status once
const initialElapsed = Math.floor((Date.now() - serverTimestamp) / 1000);
const isStale = initialElapsed > maxAge;
// Set the status once on page load
status.className = isStale ? 'status stale' : 'status fresh';
status.textContent = isStale
? '🔄 This response was served from a stale cache'
: '✨ This response was fresh';
// Set initial elapsed time
elapsedTime.textContent = initialElapsed;
// Update elapsed time counter and refresh message
setInterval(() => {
const elapsed = Math.floor((Date.now() - serverTimestamp) / 1000);
elapsedTime.textContent = elapsed;
// Update the refresh status message
if (elapsed <= maxAge) {
refreshStatus.textContent = \`If you refresh now, you'll get a fresh response from cache (still within max-age of \${maxAge} seconds)\`;
} else if (elapsed <= maxAge + ${STALE_WHILE_REVALIDATE}) {
refreshStatus.textContent = \`If you refresh now, you'll get a stale response while the server revalidates (stale for \${elapsed - maxAge} seconds)\`;
} else {
refreshStatus.textContent = \`If you refresh now, you'll get a fresh response (cache expired)\`;
}
}, 1000);
</script>
</body>
</html>
`);
});
const PORT = 6969;
server.listen(PORT, () => {
console.log(`Server running on port http://localhost:${PORT}`);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment