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
- Start development server:
npm run dev
- Open browser console to see transformation logs
- Check Network tab for proxy requests
- 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
- Check console for proxy errors
- Verify CORS headers are set
- Test with different image URLs
- Check network connectivity to proxy services
SharedArrayBuffer Not Available
- Verify CORS headers are set in server configuration
- Check that site is served over HTTPS (or localhost)
- Ensure browser supports SharedArrayBuffer
Proxy Service Unavailable
- Check if allorigins.win is accessible
- Consider using alternative CORS proxy services
- 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
- CORS headers are now required for SharedArrayBuffer
- Image URLs automatically transformed in development
- No changes needed to existing image loading code
- Test thoroughly in both development and production
Adding New Image Sources
- Add specific proxy for frequently used domains
- Update
transformImageUrlForCors
function - Add CORS headers to proxy configuration
- Test with sample images
Future Enhancements
Possible Improvements
- Local Proxy Server: Run dedicated proxy server for development
- Caching: Cache proxy responses for better performance
- Fallback Chain: Multiple proxy services for reliability
- Image Optimization: Compress/resize images through proxy
- Analytics: Track image loading success/failure rates
Alternative Approaches
- Service Worker: Intercept image requests at service worker level
- Build-time Processing: Pre-process images during build
- CDN Integration: Use CDN with proper CORS headers
- 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.