[go: up one dir, main page]

Visit the CORS tutorial at web.dev for background on how to use CORS.

Browser support

Testing Your CORS Configuration

After configuring CORS on your server, it's important to verify that your configuration works correctly. This guide covers multiple testing approaches to ensure your CORS setup is working as expected.

Using curl

The curl command-line tool is the quickest way to test CORS headers. Here are common test scenarios:

Test a Simple Request

Test a basic GET request with an Origin header:

# Test with allowed origin
curl -H "Origin: https://example.com" \
     -I https://your-api.com/endpoint

# Expected response headers:
# Access-Control-Allow-Origin: https://example.com
# Vary: Origin

Test Preflight Request

For requests with custom headers or methods like PUT/DELETE, browsers send a preflight OPTIONS request:

# Test preflight
curl -H "Origin: https://example.com" \
     -H "Access-Control-Request-Method: POST" \
     -H "Access-Control-Request-Headers: Content-Type, Authorization" \
     -X OPTIONS \
     -I https://your-api.com/endpoint

# Expected response headers:
# Access-Control-Allow-Origin: https://example.com
# Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
# Access-Control-Allow-Headers: Content-Type, Authorization
# Access-Control-Max-Age: 86400

Test Actual Request with Custom Headers

After preflight succeeds, test the actual request:

# POST request with custom headers
curl -H "Origin: https://example.com" \
     -H "Content-Type: application/json" \
     -H "Authorization: Bearer token123" \
     -X POST \
     -d '{"test":"data"}' \
     https://your-api.com/endpoint

Test Disallowed Origin

Verify that unauthorized origins are rejected:

# Test with disallowed origin
curl -H "Origin: https://evil.com" \
     -I https://your-api.com/endpoint

# Should NOT return Access-Control-Allow-Origin header

Test with Credentials

If your API supports credentials (cookies, auth):

# Test with credentials
curl -H "Origin: https://example.com" \
     --cookie "session=abc123" \
     -I https://your-api.com/endpoint

# Expected response headers:
# Access-Control-Allow-Origin: https://example.com
# Access-Control-Allow-Credentials: true
# Vary: Origin

Using Browser DevTools

Browser developer tools provide detailed CORS debugging information:

Network Tab Inspection

  1. Open DevTools (F12 or right-click → Inspect)
  2. Go to the Network tab
  3. Make a cross-origin request from your application
  4. Look for the OPTIONS request (preflight) if using custom headers/methods
  5. Click on the request to view headers
  6. Check Response Headers for CORS headers:
    • Access-Control-Allow-Origin
    • Access-Control-Allow-Methods
    • Access-Control-Allow-Headers
    • Access-Control-Allow-Credentials
    • Vary: Origin

Console Error Messages

The browser console displays helpful CORS error messages. Common patterns:

Test in Browser Console

Quickly test CORS from the browser console:

// Simple GET request
fetch('https://your-api.com/endpoint', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json'
  }
})
.then(response => response.json())
.then(data => console.log('Success:', data))
.catch(error => console.error('CORS Error:', error));

// POST with credentials
fetch('https://your-api.com/endpoint', {
  method: 'POST',
  credentials: 'include',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer token123'
  },
  body: JSON.stringify({test: 'data'})
})
.then(response => response.json())
.then(data => console.log('Success:', data))
.catch(error => console.error('CORS Error:', error));

Common CORS Errors

No 'Access-Control-Allow-Origin' header is present

Cause: Server is not sending CORS headers.

Solution: Configure your server to send the Access-Control-Allow-Origin header. See the server-specific guides for your platform.

The 'Access-Control-Allow-Origin' header contains multiple values

Cause: CORS headers are being set in multiple places (e.g., both application code and web server config).

Solution: Choose one configuration method and remove the duplicate. Check both your application code and web server configuration.

Credential is not supported if CORS header is '*'

Cause: Using Access-Control-Allow-Origin: * with Access-Control-Allow-Credentials: true.

Solution: Specify exact origin instead of wildcard when using credentials:

Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true

Method [METHOD] is not allowed by Access-Control-Allow-Methods

Cause: The HTTP method you're using is not listed in Access-Control-Allow-Methods.

Solution: Add the method to your CORS configuration:

Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS

Request header field [HEADER] is not allowed

Cause: Custom header is not listed in Access-Control-Allow-Headers.

Solution: Add the header to your CORS configuration:

Access-Control-Allow-Headers: Content-Type, Authorization, X-Custom-Header

Redirect is not allowed for a preflight request

Cause: Server is redirecting the OPTIONS preflight request.

Solution: Ensure preflight OPTIONS requests return 204 No Content without redirects. Check for trailing slash redirects or authentication redirects on OPTIONS requests.

Expected Response Headers

A properly configured CORS server should return these headers:

For All CORS Requests

Access-Control-Allow-Origin: https://example.com
Vary: Origin

For Preflight OPTIONS Requests

Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400
Vary: Origin

With Credentials

Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true
Vary: Origin

With Exposed Headers

If your API returns custom headers that the client needs to access:

Access-Control-Expose-Headers: X-Custom-Header, X-Total-Count

Troubleshooting Checklist

If CORS isn't working, check these common issues:

  1. Headers sent before output: In PHP, CGI, and similar environments, headers must be set before any output
  2. Server config vs application code: Ensure you're not setting CORS headers in both places (can cause duplicates)
  3. OPTIONS method handled: Ensure your server responds to OPTIONS requests with 204 No Content
  4. Vary header included: Always include Vary: Origin when dynamically setting the origin
  5. No trailing slashes: URL mismatches (with/without trailing slash) can cause issues
  6. Authentication on OPTIONS: Preflight OPTIONS should NOT require authentication
  7. Wildcard with credentials: Cannot use * with Access-Control-Allow-Credentials: true
  8. HTTPS requirements: Some browsers require HTTPS for certain CORS scenarios
  9. Port numbers: Different ports are considered different origins (https://example.com:3000 ≠ https://example.com:8080)
  10. Cache issues: Clear browser cache or use incognito/private mode for testing

Who’s behind this

Monsur Hossain and Michael Hausenblas

Contribute

The content on this site stays fresh thanks to help from users like you! If you have suggestions or would like to contribute, fork us on GitHub.

Buy the book

Save 39% on CORS in Action with promotional code hossainco at manning.com/hossain