このページの内容

Awesome .htaccess Snippets

.htaccess Snippetsを扱う資料や関連プロジェクトをまとめたAwesomeリストです。

目次

書き換えとリダイレクト

注: mod_rewriteがインストールされ、有効になっていることを前提とします。

wwwを強制

RewriteEngine on
RewriteCond %{HTTP_HOST} ^example\.com [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [L,R=301,NC]

汎用的にwwwを強制

RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

これは_任意の_ドメインで機能します。出典

非wwwを強制

wwwと非wwwのどちらを使うべきかは今も議論続いています。裸のドメインを好む場合は次の設定を使えます。

RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.example\.com [NC]
RewriteRule ^(.*)$ https://example.com/$1 [L,R=301]

汎用的に非wwwを強制

RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.
RewriteCond %{HTTPS}s ^on(s)|off
RewriteCond http%1://%{HTTP_HOST} ^(https?://)(www\.)?(.+)$
RewriteRule ^ %1%3%{REQUEST_URI} [R=301,L]

HTTPSを強制

RewriteEngine on
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

# Note: It’s also recommended to enable HTTP Strict Transport Security (HSTS)
# on your HTTPS website to help prevent man-in-the-middle attacks.
# See https://developer.mozilla.org/en-US/docs/Web/Security/HTTP_strict_transport_security
<IfModule mod_headers.c>
    # Remove "includeSubDomains" if you don't want to enforce HSTS on all subdomains
    Header always set Strict-Transport-Security "max-age=31536000;includeSubDomains"
</IfModule>

プロキシ背後でHTTPSを強制

サーバーの前段にTLS終端を行うプロキシがある場合に便利です。

RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

末尾スラッシュを強制

RewriteCond %{REQUEST_URI} /+[^\.]+$
RewriteRule ^(.+[^/])$ %{REQUEST_URI}/ [R=301,L]

末尾スラッシュを削除

このスニペットは、実在するディレクトリを除き、末尾がスラッシュのパスをスラッシュなしのパスへリダイレクトします。たとえば https://www.example.com/blog/https://www.example.com/blog へ変換します。各ページに正規URLを設けることが推奨されるため、SEOでも重要です。

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [R=301,L]

Source

単一ページをリダイレクト

Redirect 301 /oldpage.html https://www.example.com/newpage.html
Redirect 301 /oldpage2.html https://www.example.com/folder/

Source

RedirectMatchでリダイレクト

RedirectMatch 301 /subdirectory(.*) https://www.newsite.com/newfolder/$1
RedirectMatch 301 ^/(.*).htm$ /$1.html
RedirectMatch 301 ^/200([0-9])/([^01])(.*)$ /$2$3
RedirectMatch 301 ^/category/(.*)$ /$1
RedirectMatch 301 ^/(.*)/htaccesselite-ultimate-htaccess-article.html(.*) /htaccess/htaccess.html
RedirectMatch 301 ^/(.*).html/1/(.*) /$1.html$2
RedirectMatch 301 ^/manual/(.*)$ https://www.php.net/manual/$1
RedirectMatch 301 ^/old-directory/(.*)$ /new-directory/$1
RedirectMatch 301 ^/z/(.*)$ https://static.askapache.com/$1

Source

単一ディレクトリのエイリアス

RewriteEngine On
RewriteRule ^source-directory/(.*) /target-directory/$1 [R=301,L]

パスをスクリプトへ割り当て

FallbackResource /index.fcgi

この例では、あるディレクトリに index.fcgi があり、そのディレクトリ内でファイル名やディレクトリ名として解決できないリクエストを index.fcgi へ送ります。baz.foo/some/cool/pathbaz.foo/index.fcgibaz.foo へのリクエストにも対応)で処理しながら、baz.foo/css/style.css などを維持したい場合に便利です。元のパスは、スクリプト環境に公開されるPATH_INFO環境変数から取得できます。

RewriteEngine On
RewriteRule ^$ index.fcgi/ [QSA,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.fcgi/$1 [QSA,L]

これはFallbackResourceディレクティブより効率が劣ります(mod_rewriteFallbackResourceだけを扱うより複雑なため)が、より柔軟です。

サイト全体をリダイレクト

Redirect 301 / https://newsite.com/

この方法ではリンクのパスを維持します。つまりwww.oldsite.com/some/crazy/link.htmlwww.newsite.com/some/crazy/link.htmlになります。サイトを新しいドメインへ移転する場合に非常に便利です。出典

クリーンURLのエイリアス

このスニペットを使うと、example.com/users のような、example.com/users.php に代わるPHP拡張子なしの「クリーン」URLを利用できます。

RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^([^.]+)$ $1.php [NC,L]

Source

URLをリダイレクト対象から除外

このスニペットはURLをリダイレクト対象から除外します。たとえばリダイレクト規則を設定しつつ、検索エンジンが想定どおりアクセスできるようrobots.txtだけを除外できます。

RewriteEngine On
RewriteRule ^robots.txt - [L]

セキュリティ

すべてのアクセスを拒否

Require all denied

でも、これによりあなたのコンテンツからもアクセスが遮られます!したがって紹介するのは…

自分以外のアクセスを拒否

Require all denied
Require ip xxx.xxx.xxx.xxx

xxx.xxx.xxx.xxx is your IP. If you replace the last three digits with 0/12 for example, this will specify a range of IPs within the same network, thus saving you the trouble to list all allowed IPs separately. Source

もちろん、逆のバージョンもあります:

スパマー以外のアクセスを許可

Require all granted
Require not ip xxx.xxx.xxx.xxx
Require not ip xxx.xxx.xxx.xxy

隠しファイルとディレクトリへのアクセスを拒否

名前がドット.で始まる隠しファイルとディレクトリ(.htaccess.htpasswd.git.hgなど)は、ほぼ常に保護すべきです。

RewriteCond %{SCRIPT_FILENAME} -d [OR]
RewriteCond %{SCRIPT_FILENAME} -f
RewriteRule "(^|/)\." - [F]

代わりに「Not Found」エラーを返し、攻撃者へ手掛かりを与えない方法もあります。

RedirectMatch 404 /\..*$

バックアップとソースファイルへのアクセスを拒否

これらのファイルはVi/Vimなどのテキスト/HTMLエディターが残す場合があり、公開されると重大なセキュリティリスクになります。

<FilesMatch "(\.(bak|config|dist|fla|inc|ini|log|psd|sh|sql|swp)|~)$">
    Require all denied
</FilesMatch>

Source

ディレクトリ一覧を無効化

Options All -Indexes

画像の直リンクを無効化

RewriteEngine on
# Remove the following line if you want to block blank referrer too
RewriteCond %{HTTP_REFERER} !^$

RewriteCond %{HTTP_REFERER} !^https?://(.+\.)?example.com [NC]
RewriteRule \.(jpe?g|png|gif|bmp|webp|avif|svg|ico)$ - [NC,F,L]

# If you want to display a “blocked” banner in place of the hotlinked image,
# replace the above rule with:
# RewriteRule \.(jpe?g|png|gif|bmp|webp|avif|svg|ico) https://example.com/blocked.png [R,L]

特定ドメインの画像直リンクを無効化

特定の悪質なサイトからの画像直リンクだけを無効にしたい場合があります。

RewriteEngine on
RewriteCond %{HTTP_REFERER} ^https?://(.+\.)?badsite\.com [NC,OR]
RewriteCond %{HTTP_REFERER} ^https?://(.+\.)?badsite2\.com [NC,OR]
RewriteRule \.(jpe?g|png|gif|bmp|webp|avif|svg|ico)$ - [NC,F,L]

# If you want to display a “blocked” banner in place of the hotlinked image,
# replace the above rule with:
# RewriteRule \.(jpe?g|png|gif|bmp|webp|avif|svg|ico) https://example.com/blocked.png [R,L]

ディレクトリをパスワード保護

まず、システム内の任意の場所に.htpasswdファイルを作成します。

htpasswd -c /home/fellowship/.htpasswd boromir

次に、それを認証へ使用します。

AuthType Basic
AuthName "One does not simply"
AuthUserFile /home/fellowship/.htpasswd
Require valid-user

ファイルをパスワード保護

AuthName "One still does not simply"
AuthType Basic
AuthUserFile /home/fellowship/.htpasswd

<Files "one-ring.o">
Require valid-user
</Files>

<FilesMatch ^((one|two|three)-rings?\.o)$>
Require valid-user
</FilesMatch>

リファラーで訪問者をブロック

特定のドメインをリファラーとして訪れたすべてのユーザーのアクセスを拒否します。 Source

RewriteEngine on
# Options +FollowSymlinks
RewriteCond %{HTTP_REFERER} somedomain\.com [NC,OR]
RewriteCond %{HTTP_REFERER} anotherdomain\.com
RewriteRule .* - [F]

特定のUser-Agentをブロック

特定のUser-Agentによるサイトへのアクセスを遮断します。スクレイパーや悪質なボットのブロックに便利です。

RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} BadBot [NC,OR]
RewriteCond %{HTTP_USER_AGENT} EvilScraper [NC]
RewriteRule .* - [F,L]

サイトのフレーム表示を防止

特定のURIだけは許可しつつ、ウェブサイトがiframeタグ内へ埋め込まれることを防止します。

SetEnvIf Request_URI "/starry-night" allow_framing=true
Header set X-Frame-Options SAMEORIGIN env=!allow_framing

Content Security Policy(CSP)

Content Security Policyヘッダーは、読み込みを許可する動的リソースを宣言し、クロスサイトスクリプティング(XSS)などのコードインジェクション攻撃を軽減します。

<IfModule mod_headers.c>
    Header set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'"
</IfModule>

用途に合わせてディレクティブを調整してください。利用可能な全ディレクティブはCSPリファレンスを参照してください。

MIMEタイプスニッフィングを防止

ブラウザーがリソースのMIMEタイプを推測(スニッフィング)することを防ぎます。ブラウザーはサーバーの指定を信頼し、想定タイプと一致しないリソースをブロックします。

<IfModule mod_headers.c>
    Header set X-Content-Type-Options "nosniff"
</IfModule>

Referrer Policyを設定

リクエストに含めるリファラー情報の量を制御します。完全なURLが外部サイトへ漏れるのを防ぎ、ユーザーのプライバシーを保護します。

<IfModule mod_headers.c>
    Header set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>

Permissions Policyを設定

カメラ、マイク、位置情報など、サイトが利用できるブラウザー機能を制限します。

<IfModule mod_headers.c>
    Header set Permissions-Policy "camera=(), microphone=(), geolocation=(), interest-cohort=()"
</IfModule>

サーバー署名を削除

ApacheがHTTPヘッダーやエラーページでバージョン番号とOS情報を公開するのを防ぎます。

ServerSignature Off

パフォーマンス

テキストファイルを圧縮

<IfModule mod_deflate.c>

    # Force compression for mangled headers.
    # https://developer.yahoo.com/blogs/ydn/pushing-beyond-gzipping-25601.html
    <IfModule mod_setenvif.c>
        <IfModule mod_headers.c>
            SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
            RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
        </IfModule>
    </IfModule>

    # Compress all output labeled with one of the following MIME-types
    # (mod_filter is required for Apache 2.4)
    <IfModule mod_filter.c>
        AddOutputFilterByType DEFLATE application/atom+xml \
                                      application/javascript \
                                      application/json \
                                      application/rss+xml \
                                      application/x-font-ttf \
                                      application/x-web-app-manifest+json \
                                      application/xhtml+xml \
                                      application/xml \
                                      font/opentype \
                                      image/svg+xml \
                                      image/x-icon \
                                      text/css \
                                      text/html \
                                      text/plain \
                                      text/xml
    </IfModule>

</IfModule>

Source

Expiresヘッダーを設定

Expires headers tell the browser whether they should request a specific file from the server or just grab it from the cache. It is advisable to set static content’s expires headers to something far in the future.

ファイル名ベースのキャッシュバスティングでバージョンを管理していない場合は、CSSやJSなどのキャッシュ期間を1週間程度へ短縮することを検討してください。出典

<IfModule mod_expires.c>
    ExpiresActive on
    ExpiresDefault                                      "access plus 1 month"

  # CSS
    ExpiresByType text/css                              "access plus 1 year"

  # Data interchange
    ExpiresByType application/json                      "access plus 0 seconds"
    ExpiresByType application/xml                       "access plus 0 seconds"
    ExpiresByType text/xml                              "access plus 0 seconds"

  # Favicon (cannot be renamed!)
    ExpiresByType image/x-icon                          "access plus 1 week"

  # HTML
    ExpiresByType text/html                             "access plus 0 seconds"

  # JavaScript
    ExpiresByType application/javascript                "access plus 1 year"

  # Manifest files
    ExpiresByType application/x-web-app-manifest+json   "access plus 0 seconds"

  # Media
    ExpiresByType audio/ogg                             "access plus 1 month"
    ExpiresByType image/gif                             "access plus 1 month"
    ExpiresByType image/jpeg                            "access plus 1 month"
    ExpiresByType image/png                             "access plus 1 month"
    ExpiresByType video/mp4                             "access plus 1 month"
    ExpiresByType video/ogg                             "access plus 1 month"
    ExpiresByType video/webm                            "access plus 1 month"

  # Web feeds
    ExpiresByType application/atom+xml                  "access plus 1 hour"
    ExpiresByType application/rss+xml                   "access plus 1 hour"

  # Web fonts
    ExpiresByType application/font-woff2                "access plus 1 month"
    ExpiresByType application/font-woff                 "access plus 1 month"
    ExpiresByType application/x-font-ttf                "access plus 1 month"
    ExpiresByType font/opentype                         "access plus 1 month"
    ExpiresByType image/svg+xml                         "access plus 1 month"
</IfModule>

Cache-Controlヘッダーを設定

Cache-Control headers provide more fine-grained control over browser caching than Expires headers. You can use both together for maximum compatibility.

<IfModule mod_headers.c>
    # Cache CSS and JS for 1 year
    <FilesMatch "\.(css|js)$">
        Header set Cache-Control "max-age=31536000, public"
    </FilesMatch>

    # Cache images for 1 month
    <FilesMatch "\.(jpe?g|png|gif|webp|avif|svg|ico)$">
        Header set Cache-Control "max-age=2592000, public"
    </FilesMatch>

    # Cache fonts for 1 month
    <FilesMatch "\.(woff2?|ttf|otf)$">
        Header set Cache-Control "max-age=2592000, public"
    </FilesMatch>

    # Do not cache HTML
    <FilesMatch "\.(html|htm)$">
        Header set Cache-Control "no-cache, no-store, must-revalidate"
    </FilesMatch>
</IfModule>

eTagを無効化

ETagヘッダーを削除すると、キャッシュとブラウザーはファイルを検証できなくなり、Cache-ControlExpiresヘッダーに依存します。出典

<IfModule mod_headers.c>
    Header unset ETag
</IfModule>
FileETag None

その他

PHP変数を設定

php_value <key> <val>

# For example:
php_value upload_max_filesize 50M
php_value max_execution_time 240

カスタムエラーページ

ErrorDocument 500 "Houston, we have a problem."
ErrorDocument 401 https://error.example.com/mordor.html
ErrorDocument 404 /errors/halflife3.html

カスタムメンテナンスページ

特定のIPアドレスからのアクセスだけを許可し、その他すべてのトラフィックをメンテナンスページへリダイレクトします。

RewriteEngine on
RewriteCond %{REMOTE_ADDR} !^xxx\.xxx\.xxx\.xxx
RewriteCond %{REQUEST_URI} !/maintenance.html$ [NC]
RewriteCond %{REQUEST_URI} !\.(css|js|png|jpe?g|gif|svg|ico)$ [NC]
RewriteRule .* /maintenance.html [R=503,L]

メンテナンス中もアクセスできるよう、xxx.xxx.xxx.xxxを自分のIPアドレスへ置き換えてください。

ダウンロードを強制

コンテンツを表示せず、ブラウザーにダウンロードさせたい場合があります。

<Files *.md>
    ForceType application/octet-stream
    Header set Content-Disposition attachment
</Files>

この陰には陽があるのです:

ダウンロードを防止

コンテンツをダウンロードせず、ブラウザーに表示させたい場合があります。

<FilesMatch "\.(tex|log|aux)$">
    Header set Content-Type text/plain
</FilesMatch>

クロスドメインフォントを許可

CDNから配信されるウェブフォントは、CORSのためFirefoxで動作しない場合があります。このスニペットで解決できます。

<IfModule mod_headers.c>
    <FilesMatch "\.(otf|ttc|ttf|woff|woff2)$">
        Header set Access-Control-Allow-Origin "*"
    </FilesMatch>
</IfModule>

Source

CORSを有効化

サイトでCross-Origin Resource Sharing(CORS)を有効にし、他のドメインからサーバーへのリクエストを許可します。

<IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
    Header set Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS"
    Header set Access-Control-Allow-Headers "Content-Type, Authorization"
</IfModule>

特定のドメインに制限するには、*https://example.com などのドメインへ置き換えます。

UTF-8を自動設定

テキストコンテンツは常にUTF-8でエンコードすべきです。

# Use UTF-8 encoding for anything served text/plain or text/html
AddDefaultCharset utf-8

# Force UTF-8 for a number of file formats
AddCharset utf-8 .atom .css .js .json .rss .vtt .xml

Source

カスタムMIMEタイプを設定

Apacheが標準では認識しないファイル形式にカスタムMIMEタイプを定義します。

AddType application/manifest+json .webmanifest
AddType application/wasm .wasm
AddType application/x-ndjson .ndjson
AddType text/vtt .vtt

別のPHPバージョンへ切り替え

共有ホスティングでは複数のPHPバージョンがインストールされていることがあり、サイトごとに特定バージョンを使いたい場合があります。次のスニペットでPHPバージョンを切り替えます。

AddHandler application/x-httpd-php84 .php

# Alternatively, you can use AddType
AddType application/x-httpd-php84 .php

WebP/AVIF画像を配信

元のjpg/pngと同じ名前のモダン形式画像(AVIFまたはWebP)があれば、代わりに配信します。ブラウザーが両方に対応する場合はAVIFを優先します。

RewriteEngine On

# Serve AVIF if supported and available
RewriteCond %{HTTP_ACCEPT} image/avif
RewriteCond %{DOCUMENT_ROOT}/$1.avif -f
RewriteRule (.+)\.(jpe?g|png)$ $1.avif [T=image/avif,E=accept:1]

# Otherwise, serve WebP if supported and available
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{DOCUMENT_ROOT}/$1.webp -f
RewriteRule (.+)\.(jpe?g|png)$ $1.webp [T=image/webp,E=accept:1]