Answer
Whistle provides multiple ways to handle cross-origin issues, allowing quick resolution of CORS-related problems in development environments.
Cross-Origin Basics
1. What is Cross-Origin
Cross-origin refers to browser security restrictions that limit web pages from one domain from initiating requests to resources on another domain.
Same-Origin Policy Restrictions:
- Different protocols (http vs https)
- Different domains (example.com vs test.com)
- Different ports (80 vs 8080)
2. CORS Response Headers
Solving cross-origin requires the server to return correct CORS response headers:
- Access-Control-Allow-Origin: Allowed origins
- Access-Control-Allow-Methods: Allowed HTTP methods
- Access-Control-Allow-Headers: Allowed request headers
- Access-Control-Allow-Credentials: Whether credentials are allowed
- Access-Control-Max-Age: Cache time for preflight requests
Solving Cross-Origin with Whistle
1. Add CORS Response Headers
Create CORS response headers file: cors-headers.json
json{ "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS, PATCH", "Access-Control-Allow-Headers": "Content-Type, Authorization, X-Requested-With", "Access-Control-Allow-Credentials": "true", "Access-Control-Max-Age": "86400" }
Configure rule:
shellwww.example.com resHeaders://{cors-headers.json} api.example.com resHeaders://{cors-headers.json}
2. For Specific Domains
Create CORS response headers for specific domain: cors-specific.json
json{ "Access-Control-Allow-Origin": "https://www.myapp.com", "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS", "Access-Control-Allow-Headers": "Content-Type, Authorization", "Access-Control-Allow-Credentials": "true" }
Configure rule:
shellapi.example.com resHeaders://{cors-specific.json}
3. Handle Preflight Requests
Create script: handle-preflight.js
javascriptmodule.exports = function(req, res) { // Handle OPTIONS preflight requests if (req.method === 'OPTIONS') { res.statusCode = 204; res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization'); res.setHeader('Access-Control-Max-Age', '86400'); res.end(); } };
Configure rule:
shellapi.example.com reqScript://{handle-preflight.js}
Advanced Cross-Origin Handling
1. Dynamically Set Allow-Origin
Create script: dynamic-cors.js
javascriptmodule.exports = function(req, res) { const originalEnd = res.end; res.end = function(chunk, encoding) { // Dynamically set allowed origin const origin = req.headers['origin']; if (origin) { res.setHeader('Access-Control-Allow-Origin', origin); res.setHeader('Access-Control-Allow-Credentials', 'true'); } originalEnd.call(res, chunk, encoding); }; };
Configure rule:
shellapi.example.com resScript://{dynamic-cors.js}
2. Set Different CORS Policies Based on Request Path
Create script: path-based-cors.js
javascriptmodule.exports = function(req, res) { const originalEnd = res.end; res.end = function(chunk, encoding) { // Set different CORS policies based on path if (req.url.startsWith('/api/public/')) { res.setHeader('Access-Control-Allow-Origin', '*'); } else if (req.url.startsWith('/api/private/')) { const origin = req.headers['origin']; if (origin && origin.includes('myapp.com')) { res.setHeader('Access-Control-Allow-Origin', origin); res.setHeader('Access-Control-Allow-Credentials', 'true'); } } originalEnd.call(res, chunk, encoding); }; };
Configure rule:
shellapi.example.com resScript://{path-based-cors.js}
3. Proxy to Same Origin
Use forward operator:
shellapi.example.com forward http://127.0.0.1:3000
Or use host operator:
shellapi.example.com host 127.0.0.1:3000
Common Cross-Origin Scenarios
1. Frontend Local Development Debugging
Scenario:
Frontend on localhost:3000, backend on api.example.com
Solution:
shell# Add CORS response headers api.example.com resHeaders://{cors-headers.json} # Or proxy backend to local api.example.com host 127.0.0.1:8080
2. Communication Between Multiple Subdomains
Scenario:
www.example.com needs to access api.example.com
Solution:
shell# Allow specific subdomain api.example.com resHeaders://{cors-subdomain.json}
cors-subdomain.json:
json{ "Access-Control-Allow-Origin": "https://www.example.com", "Access-Control-Allow-Credentials": "true" }
3. Requests with Credentials
Scenario: Requests that need to carry Cookie or Authorization headers
Solution:
shellapi.example.com resHeaders://{cors-with-credentials.json}
cors-with-credentials.json:
json{ "Access-Control-Allow-Origin": "https://www.myapp.com", "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Content-Type, Authorization" }
Cross-Origin Debugging Tips
1. View Preflight Requests
In whistle management interface:
- Click "Network" tab
- Filter requests with "OPTIONS" method
- View request and response headers
- Check if CORS response headers are correct
2. Verify CORS Configuration
Create verification script: verify-cors.js
javascriptmodule.exports = function(req, res) { console.log('Request Origin:', req.headers['origin']); console.log('Request Method:', req.method); console.log('Request Headers:', req.headers['access-control-request-headers']); const originalEnd = res.end; res.end = function(chunk, encoding) { console.log('Response CORS Headers:'); console.log(' Access-Control-Allow-Origin:', res.getHeader('Access-Control-Allow-Origin')); console.log(' Access-Control-Allow-Methods:', res.getHeader('Access-Control-Allow-Methods')); console.log(' Access-Control-Allow-Headers:', res.getHeader('Access-Control-Allow-Headers')); originalEnd.call(res, chunk, encoding); }; };
Configure rule:
shellapi.example.com resScript://{verify-cors.js}
3. Simulate Different Origins
Create script: simulate-origin.js
javascriptmodule.exports = function(req, res) { // Simulate different request origins const origins = [ 'https://www.example.com', 'https://test.example.com', 'https://localhost:3000' ]; // Randomly select an origin const randomOrigin = origins[Math.floor(Math.random() * origins.length)]; req.headers['origin'] = randomOrigin; console.log('Simulated Origin:', randomOrigin); };
Configure rule:
shellapi.example.com reqScript://{simulate-origin.js}
Best Practices
-
Use Relaxed CORS Policies in Development
- Allow all origins:
* - Convenient for development and testing
- Allow all origins:
-
Use Strict CORS Policies in Production
- Only allow specific origins
- Enable credential verification
-
Regularly Check CORS Configuration
- Ensure response headers are correct
- Avoid security vulnerabilities
-
Use Environment Variables to Manage CORS Configuration
- Development environment: relaxed policy
- Production environment: strict policy
-
Document CORS Policies
- Record allowed origins
- Explain special handling logic