Apache .htaccess CORS Configuration

Set up CORS headers in Apache using mod_headers and .htaccess. Covers single origin, dynamic origin with SetEnvIf, and handling preflight requests.

Framework Config

Detailed Explanation

Apache CORS with mod_headers

Apache's mod_headers module provides the Header directive for adding response headers. Combined with SetEnvIf, you can implement dynamic origin validation similar to Nginx's map block.

Prerequisites

Ensure mod_headers is enabled:

a2enmod headers
systemctl reload apache2

Simple .htaccess — Single Origin

<IfModule mod_headers.c>
    Header always set Access-Control-Allow-Origin "https://app.example.com"
    Header always set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
    Header always set Access-Control-Allow-Headers "Content-Type, Authorization"
    Header always set Access-Control-Max-Age "3600"
    Header always set Access-Control-Allow-Credentials "true"
    Header always set Vary "Origin"
</IfModule>

# Handle preflight
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=204,L]

Dynamic Origin with SetEnvIf

<IfModule mod_headers.c>
    SetEnvIf Origin "^https://(app|admin)\.example\.com$" CORS_ORIGIN=$0
    Header always set Access-Control-Allow-Origin "%{CORS_ORIGIN}e" env=CORS_ORIGIN
    Header always set Access-Control-Allow-Credentials "true" env=CORS_ORIGIN
    Header always set Vary "Origin" env=CORS_ORIGIN
    Header always set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" env=CORS_ORIGIN
    Header always set Access-Control-Allow-Headers "Content-Type, Authorization" env=CORS_ORIGIN
    Header always set Access-Control-Max-Age "3600" env=CORS_ORIGIN
</IfModule>

How SetEnvIf Works

SetEnvIf Origin "regex" CORS_ORIGIN=$0 captures the entire matched Origin header value into an environment variable. The env=CORS_ORIGIN condition on each Header directive means headers are only set when the variable exists — i.e., when the origin matched the regex.

Key Differences from Nginx

  • Apache evaluates .htaccess per-request, which is slower than Nginx's compiled config but more flexible for shared hosting.
  • The always keyword in Apache's Header directive works similarly to Nginx — it adds headers even on error responses.
  • Apache's RewriteRule handles the OPTIONS response, whereas Nginx uses return 204.

Use Case

A developer hosting a PHP API on shared hosting (cPanel, Plesk) where they only have access to .htaccess files, not the main Apache config. They need CORS headers for their JavaScript frontend hosted on a different domain.

Try It — CORS Header Builder

Open full tool