Mixed Content and Upgrade-Insecure-Requests
Mixed Content and Upgrade-Insecure-Requests
Mixed content errors occur when HTTPS pages load HTTP resources:
// Common Error: Mixed content blocked
// Console: Mixed Content: The page was loaded over HTTPS, but requested an insecure
// resource. This request has been blocked; the content must be served over HTTPS.
// SOLUTION 1: Use upgrade-insecure-requests
Content-Security-Policy: upgrade-insecure-requests;
// SOLUTION 2: Implement resource URL helper
class SecureResourceHelper {
constructor(forceHTTPS = true) {
this.forceHTTPS = forceHTTPS;
}
secureUrl(url) {
if (!url) return url;
// Already HTTPS or protocol-relative
if (url.startsWith('https://') || url.startsWith('//')) {
return url;
}
// Relative URL
if (!url.startsWith('http://')) {
return url;
}
// Convert HTTP to HTTPS if forced
if (this.forceHTTPS) {
return url.replace(/^http:/, 'https:');
}
// Make protocol-relative
return url.replace(/^https?:/, '');
}
// Middleware to automatically secure URLs in responses
middleware() {
return (req, res, next) => {
const originalRender = res.render;
res.render = (view, options, callback) => {
options = options || {};
options.secureUrl = (url) => this.secureUrl(url);
originalRender.call(res, view, options, callback);
};
next();
};
}
}
// SOLUTION 3: Content transformation proxy
app.use('/proxy', (req, res) => {
const targetUrl = req.query.url;
// Validate and secure URL
if (!isValidUrl(targetUrl)) {
return res.status(400).send('Invalid URL');
}
const secureUrl = targetUrl.replace(/^http:/, 'https:');
// Proxy the request
request(secureUrl)
.on('error', err => res.status(500).send('Proxy error'))
.pipe(res);
});