Implemented a comprehensive CORS proxy solution that works with both
local and remote backends during development.
## Changes
### Vite Configuration (vite.config.ts)
- Use loadEnv() to properly read VITE_API_BASE_URL from .env
- Configure proxy to forward /api/* requests to backend
- Add detailed logging for proxy requests and responses
- Support changeOrigin, rewrite, secure=false, and websockets
### API Client (src/lib/api/client.ts)
- In development: Always use /api prefix (proxied)
- In production: Use direct VITE_API_BASE_URL
- Add console logging to show proxy configuration in dev mode
- Automatic detection of environment (DEV vs PROD)
### Error Handling (route loaders)
- Fix console.error() calls that caused TypeError with circular refs
- Use error.message instead of logging full error objects
- Affects: +page.ts, matches/+page.ts
### Documentation
- docs/LOCAL_DEVELOPMENT.md: Complete rewrite with proxy explanation
- Quick start guide for both production API and local backend
- Detailed proxy flow diagrams
- Comprehensive troubleshooting section
- Clear examples and logs
- docs/CORS_PROXY.md: Technical deep-dive on proxy implementation
- How the proxy works internally
- Configuration options explained
- Testing procedures
- Common issues and solutions
- .env.example: Updated with proxy documentation
## How It Works
Development Flow:
1. Frontend makes request: /api/matches
2. Vite proxy intercepts and forwards to: ${VITE_API_BASE_URL}/matches
3. Backend responds (no CORS headers needed)
4. Proxy returns response to frontend (same-origin)
Production Flow:
1. Frontend makes request directly to: https://api.csgow.tf/matches
2. Backend responds with CORS headers
3. Browser allows request (CORS enabled on backend)
## Benefits
✅ No CORS errors in development
✅ Works with local backend (localhost:8000)
✅ Works with remote backend (api.csgow.tf)
✅ Simple configuration (just set VITE_API_BASE_URL)
✅ Detailed logging for debugging
✅ Production build unaffected (direct requests)
## Testing
Verified with production API:
- curl https://api.csgow.tf/matches ✓
- Dev server proxy logs show successful forwarding ✓
- Browser Network tab shows /api/* requests ✓
- No CORS errors in console ✓
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
66 lines
1.9 KiB
TypeScript
66 lines
1.9 KiB
TypeScript
import { sveltekit } from '@sveltejs/kit/vite';
|
|
import { defineConfig } from 'vitest/config';
|
|
import { loadEnv } from 'vite';
|
|
|
|
export default defineConfig(({ mode }) => {
|
|
// Load env file based on `mode` in the current working directory.
|
|
// Set the third parameter to '' to load all env regardless of the `VITE_` prefix.
|
|
const env = loadEnv(mode, process.cwd(), '');
|
|
const apiBaseUrl = env.VITE_API_BASE_URL || 'http://localhost:8000';
|
|
|
|
console.log('[Vite Config] API Proxy target:', apiBaseUrl);
|
|
|
|
return {
|
|
plugins: [sveltekit()],
|
|
test: {
|
|
include: ['src/**/*.{test,spec}.{js,ts}'],
|
|
globals: true,
|
|
environment: 'jsdom',
|
|
setupFiles: ['./src/tests/setup.ts'],
|
|
coverage: {
|
|
provider: 'v8',
|
|
reporter: ['text', 'json', 'html'],
|
|
exclude: [
|
|
'node_modules/',
|
|
'src/tests/',
|
|
'**/*.d.ts',
|
|
'**/*.config.*',
|
|
'**/mockData',
|
|
'**/.svelte-kit'
|
|
]
|
|
}
|
|
},
|
|
server: {
|
|
port: 5173,
|
|
strictPort: false,
|
|
proxy: {
|
|
// Proxy API requests to backend to avoid CORS issues in development
|
|
// All requests to /api/* are forwarded to the backend
|
|
'/api': {
|
|
target: apiBaseUrl,
|
|
changeOrigin: true, // Updates the Origin header to match the target
|
|
rewrite: (path) => path.replace(/^\/api/, ''), // Remove /api prefix
|
|
secure: false, // Allow self-signed certificates
|
|
ws: true, // Proxy websockets
|
|
configure: (proxy, options) => {
|
|
proxy.on('error', (err, _req, _res) => {
|
|
console.error('[Proxy Error]', err.message);
|
|
console.error('[Proxy Error] Make sure backend is running at:', apiBaseUrl);
|
|
});
|
|
proxy.on('proxyReq', (proxyReq, req, _res) => {
|
|
console.log(`[Proxy] ${req.method} ${req.url} -> ${apiBaseUrl}${proxyReq.path}`);
|
|
});
|
|
proxy.on('proxyRes', (proxyRes, req, _res) => {
|
|
console.log(`[Proxy ✓] ${req.method} ${req.url} -> ${proxyRes.statusCode}`);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
},
|
|
preview: {
|
|
port: 4173,
|
|
strictPort: false
|
|
}
|
|
};
|
|
});
|