Apache .htaccess CORS設定

Apacheでmod_headersと.htaccessを使用してCORSヘッダーを設定します。単一オリジン、SetEnvIfによる動的オリジン、プリフライトリクエスト処理を解説します。

Framework Config

詳細な説明

Apacheのmod_headersによるCORS設定

Apacheのmod_headersモジュールはレスポンスヘッダー追加用のHeaderディレクティブを提供します。SetEnvIfと組み合わせることで、Nginxのmapブロックと同様の動的オリジン検証を実装できます。

前提条件

mod_headersが有効になっていることを確認:

a2enmod headers
systemctl reload apache2

シンプルな.htaccess — 単一オリジン

<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>

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

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>

SetEnvIfの仕組み

SetEnvIf Origin "regex" CORS_ORIGIN=$0は一致したOriginヘッダー値全体を環境変数にキャプチャします。各Headerディレクティブのenv=CORS_ORIGIN条件は、変数が存在する場合(つまりオリジンが正規表現に一致した場合)のみヘッダーが設定されることを意味します。

Nginxとの主な違い

  • Apacheは.htaccessをリクエストごとに評価するため、Nginxのコンパイル済み設定より遅いですが、共有ホスティングではより柔軟です。
  • ApacheのHeaderディレクティブのalwaysキーワードはNginxと同様に動作し、エラーレスポンスでもヘッダーを追加します。
  • ApacheのRewriteRuleがOPTIONSレスポンスを処理する一方、Nginxはreturn 204を使用します。

ユースケース

共有ホスティング(cPanel、Plesk)でPHP APIをホストしている開発者が、メインApache設定ではなく.htaccessファイルのみにアクセスでき、別ドメインでホストされるJavaScriptフロントエンドのためにCORSヘッダーが必要です。

試してみる — CORS Header Builder

フルツールを開く