You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

7.5 KiB

CORS Image Loading Solution

Overview

This document describes the implementation of a comprehensive image loading solution that works in a cross-origin isolated environment (required for SharedArrayBuffer support) while accepting images from any domain.

Problem Statement

When using SharedArrayBuffer (required for absurd-sql), browsers enforce a cross-origin isolated environment with these headers:

  • Cross-Origin-Opener-Policy: same-origin
  • Cross-Origin-Embedder-Policy: require-corp

This isolation prevents loading external resources (including images) unless they have proper CORS headers, which most image hosting services don't provide.

Solution Architecture

1. Multi-Tier Proxy System

The solution uses a multi-tier approach to handle images from various sources:

Tier 1: Specific Domain Proxies (Development Only)

  • TimeSafari Images: /image-proxy/https://image.timesafari.app/
  • Flickr Images: /flickr-proxy/https://live.staticflickr.com/
  • Imgur Images: /imgur-proxy/https://i.imgur.com/
  • GitHub Raw: /github-proxy/https://raw.githubusercontent.com/
  • Unsplash: /unsplash-proxy/https://images.unsplash.com/

Tier 2: Universal CORS Proxy (Development Only)

  • Any External Domain: Uses https://api.allorigins.win/raw?url= for arbitrary domains

Tier 3: Direct Loading (Production)

  • Production Mode: All images load directly without proxying

2. Smart URL Transformation

The transformImageUrlForCors function automatically:

  • Detects the image source domain
  • Routes through appropriate proxy in development
  • Preserves original URLs in production
  • Handles edge cases (data URLs, relative paths, etc.)

Implementation Details

Configuration Files

vite.config.common.mts

server: {
  headers: {
    // Required for SharedArrayBuffer support
    'Cross-Origin-Opener-Policy': 'same-origin',
    'Cross-Origin-Embedder-Policy': 'require-corp'
  },
  proxy: {
    // Specific domain proxies with CORS headers
    '/image-proxy': { /* TimeSafari images */ },
    '/flickr-proxy': { /* Flickr images */ },
    '/imgur-proxy': { /* Imgur images */ },
    '/github-proxy': { /* GitHub raw images */ },
    '/unsplash-proxy': { /* Unsplash images */ }
  }
}

src/libs/util.ts

export function transformImageUrlForCors(imageUrl: string): string {
  // Development mode: Transform URLs to use proxies
  // Production mode: Return original URLs
  
  // Handle specific domains with dedicated proxies
  // Fall back to universal CORS proxy for arbitrary domains
}

Usage in Components

All image loading in components uses the transformation function:

// In Vue components
import { transformImageUrlForCors } from "../libs/util";

// Transform image URL before using
const imageUrl = transformImageUrlForCors(originalImageUrl);
<!-- In templates -->
<img :src="transformImageUrlForCors(imageUrl)" alt="Description" />

Benefits

SharedArrayBuffer Support

  • Maintains cross-origin isolation required for SharedArrayBuffer
  • Enables fast SQLite database operations via absurd-sql
  • Provides better performance than IndexedDB fallback

Universal Image Support

  • Handles images from any domain
  • No need to pre-configure every possible image source
  • Graceful fallback for unknown domains

Development/Production Flexibility

  • Proxy system only active in development
  • Production uses direct URLs for maximum performance
  • No proxy server required in production

Automatic Detection

  • Smart URL transformation based on domain patterns
  • Preserves relative URLs and data URLs
  • Handles edge cases gracefully

Testing

Automated Testing

Run the test suite to verify URL transformation:

import { testCorsImageTransformation } from './libs/test-cors-images';

// Console output shows transformation results
testCorsImageTransformation();

Visual Testing

Create test image elements to verify loading:

import { createTestImageElements } from './libs/test-cors-images';

// Creates visual test panel in browser
createTestImageElements();

Manual Testing

  1. Start development server: npm run dev
  2. Open browser console to see transformation logs
  3. Check Network tab for proxy requests
  4. Verify images load correctly from various domains

Security Considerations

Development Environment

  • CORS proxies are only used in development
  • External proxy services (allorigins.win) are used for testing
  • No sensitive data is exposed through proxies

Production Environment

  • All images load directly without proxying
  • No dependency on external proxy services
  • Original security model maintained

Privacy

  • Image URLs are not logged or stored by proxy services
  • Proxy requests are only made during development
  • No tracking or analytics in proxy chain

Performance Impact

Development

  • Slight latency from proxy requests
  • Additional network hops for external domains
  • More verbose logging for debugging

Production

  • No performance impact
  • Direct image loading as before
  • No proxy overhead

Troubleshooting

Common Issues

Images Not Loading in Development

  1. Check console for proxy errors
  2. Verify CORS headers are set
  3. Test with different image URLs
  4. Check network connectivity to proxy services

SharedArrayBuffer Not Available

  1. Verify CORS headers are set in server configuration
  2. Check that site is served over HTTPS (or localhost)
  3. Ensure browser supports SharedArrayBuffer

Proxy Service Unavailable

  1. Check if allorigins.win is accessible
  2. Consider using alternative CORS proxy services
  3. Temporarily disable CORS headers for testing

Debug Commands

# Check if SharedArrayBuffer is available
console.log(typeof SharedArrayBuffer !== 'undefined');

# Test URL transformation
import { transformImageUrlForCors } from './libs/util';
console.log(transformImageUrlForCors('https://example.com/image.jpg'));

# Run comprehensive tests
import { testCorsImageTransformation } from './libs/test-cors-images';
testCorsImageTransformation();

Migration Guide

From Previous Implementation

  1. CORS headers are now required for SharedArrayBuffer
  2. Image URLs automatically transformed in development
  3. No changes needed to existing image loading code
  4. Test thoroughly in both development and production

Adding New Image Sources

  1. Add specific proxy for frequently used domains
  2. Update transformImageUrlForCors function
  3. Add CORS headers to proxy configuration
  4. Test with sample images

Future Enhancements

Possible Improvements

  1. Local Proxy Server: Run dedicated proxy server for development
  2. Caching: Cache proxy responses for better performance
  3. Fallback Chain: Multiple proxy services for reliability
  4. Image Optimization: Compress/resize images through proxy
  5. Analytics: Track image loading success/failure rates

Alternative Approaches

  1. Service Worker: Intercept image requests at service worker level
  2. Build-time Processing: Pre-process images during build
  3. CDN Integration: Use CDN with proper CORS headers
  4. Local Storage: Cache images in browser storage

Conclusion

This solution provides a robust, scalable approach to image loading in a cross-origin isolated environment while maintaining the benefits of SharedArrayBuffer support. The multi-tier proxy system ensures compatibility with any image source while optimizing for performance and security.

For questions or issues, refer to the troubleshooting section or consult the development team.