Caching and CDN Optimization
Caching and CDN Optimization
Proper caching strategies can significantly reduce CSP overhead:
// CSP Caching Strategy
class CSPCachingOptimizer {
constructor() {
this.cacheStrategies = this.defineCacheStrategies();
}
defineCacheStrategies() {
return {
serverSide: {
policyCache: `
// Server-side CSP policy caching
const NodeCache = require('node-cache');
const policyCache = new NodeCache({ stdTTL: 3600 }); // 1 hour cache
class CSPPolicyCache {
generateCacheKey(req) {
// Cache key based on user context
return crypto.createHash('md5')
.update(req.headers['user-agent'] || '')
.update(req.user?.role || 'anonymous')
.update(req.headers['accept-language'] || '')
.digest('hex');
}
getPolicy(req) {
const key = this.generateCacheKey(req);
let policy = policyCache.get(key);
if (!policy) {
policy = this.generatePolicy(req);
policyCache.set(key, policy);
}
return policy;
}
invalidateCache(pattern) {
const keys = policyCache.keys();
keys.forEach(key => {
if (!pattern || key.includes(pattern)) {
policyCache.del(key);
}
});
}
}
`,
cdnIntegration: `
// CDN-friendly CSP headers
class CDNOptimizedCSP {
constructor() {
this.staticPolicies = new Map();
}
generateStaticPolicies() {
// Pre-generate policies for common scenarios
return {
'public-cached': {
policy: "default-src 'self'; script-src 'self' 'sha256-...' https://cdn.example.com",
headers: {
'Cache-Control': 'public, max-age=86400',
'Vary': 'Accept-Encoding'
}
},
'user-specific': {
policy: "default-src 'self'; script-src 'self' 'nonce-PLACEHOLDER'",
headers: {
'Cache-Control': 'private, no-cache',
'Vary': 'Accept-Encoding, Authorization'
}
}
};
}
applyCDNOptimizations(req, res, next) {
const path = req.path;
// Static assets can use cached CSP
if (path.match(/\.(js|css|jpg|png|gif|ico|woff|woff2)$/)) {
res.setHeader('Content-Security-Policy',
this.staticPolicies.get('public-cached').policy
);
} else {
// Dynamic content needs fresh CSP
const nonce = crypto.randomBytes(16).toString('base64');
const policy = this.staticPolicies.get('user-specific').policy
.replace('PLACEHOLDER', nonce);
res.setHeader('Content-Security-Policy', policy);
}
next();
}
}
`
},
clientSide: {
implementation: `
// Client-side CSP caching
class ClientCSPCache {
constructor() {
this.cache = new Map();
this.maxAge = 3600000; // 1 hour
}
getCachedNonce() {
const cached = this.cache.get('nonce');
if (cached && Date.now() - cached.timestamp < this.maxAge) {
return cached.value;
}
return null;
}
cacheNonce(nonce) {
this.cache.set('nonce', {
value: nonce,
timestamp: Date.now()
});
}
// Service Worker for CSP caching
installServiceWorker() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js').then(reg => {
console.log('Service Worker registered for CSP optimization');
});
}
}
}
`,
serviceWorker: `
// sw.js - Service Worker for CSP optimization
const CSP_CACHE = 'csp-cache-v1';
const CSP_ASSETS = [
'/js/csp-compliant-bundle.js',
'/css/styles.css'
];
self.addEventListener('install', event => {
event.waitUntil(
caches.open(CSP_CACHE).then(cache => {
return cache.addAll(CSP_ASSETS);
})
);
});
self.addEventListener('fetch', event => {
// Optimize CSP-compliant resource loading
if (event.request.destination === 'script' ||
event.request.destination === 'style') {
event.respondWith(
caches.match(event.request).then(response => {
if (response) {
// Cached response includes CSP compliance
return response;
}
return fetch(event.request).then(response => {
// Cache CSP-compliant resources
if (response.status === 200) {
const responseToCache = response.clone();
caches.open(CSP_CACHE).then(cache => {
cache.put(event.request, responseToCache);
});
}
return response;
});
})
);
}
});
`
}
};
}
}