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);
});