現在、Fedora 25 Server Edition x86_64でNginx 1.10.2を使用して、いくつかの小さな静的Webサイトをホストしています。
ファイル拡張子のないリクエスト(.html
)に対してtry_files
を想定し、.html
のないバージョンにリダイレクトする(永続的なrewrite
)ようにNginxを構成しました.*\.html
がリクエストされた場合のURL。
カスタムエラーページもあります。私がこれまで知ることができる限り、error_page
ディレクティブは、通常のエラーメッセージを返すはずのページのリダイレクトループに悩まされているため、書き換えとうまく連携しません...これですべてだと思います適切な構成:
server {
[...]
try_files $uri $uri.html $uri/index.html =404;
error_page 400 /errors/400.html;
error_page 401 /errors/401.html;
error_page 403 /errors/403.html;
error_page 404 /errors/404.html;
error_page 408 /errors/408.html;
error_page 500 /errors/500.html;
error_page 503 /errors/503.html;
# Remove "index" from URL if requesting the front page.
rewrite "^/index(\.html)?$" "/" permanent;
# Strip .html file extension, trailing slash, or "index.html".
rewrite "/(.+)(\.html|/|/index.html)$" "/$1" permanent;
[...]
}
これが私がthink Nginxがやっていることです:
/fake-page
/fake-page
、/fake-page.html
、または/fake-page/index.html
を検索します。/errors/404.html
はpermanent
フラグを使用して.htmlを取り除き、301ユーザーリダイレクトを引き起こします。私はその最後のrewrite
行でいくつかのバリエーションを試しましたが、それをlocation ^~ /errors/ {}
ブロックに入れました(これはと思います書き換えは、/-errors /ディレクトリの下にあるされないのURLにのみ適用されることを意味します)。しかし、私が行ったすべてのことにより、404ページに永続的にリダイレクトするエラー404が発生し、実際の404ステータスは返されません---またはリダイレクトループでスタックします。
@Anubiozの回答に触発されて、より簡単な解決策を見つけました。
server {
[...]
# This part's pretty common.
# Assume ".html" or ".../index.html" if the original request doesn't
# match any real files. Return error 404 if still can't find any
# matching files.
try_files $uri $uri.html $uri/index.html =404;
# Match any resulting HTTP status codes with the custom error pages
# that I designed.
error_page 400 /errors/400.html;
error_page 401 /errors/401.html;
error_page 403 /errors/403.html;
error_page 404 /errors/404.html;
error_page 408 /errors/408.html;
error_page 500 /errors/500.html;
error_page 503 /errors/503.html;
# Make sure the paths to the custom error pages are not transformed
# before sending the actual status codes to a request.
# These error pages are for *internal* use only.
location = "/errors/400.html" {
internal;
}
location = "/errors/401.html" {
internal;
}
location = "/errors/403.html" {
internal;
}
location = "/errors/404.html" {
internal;
}
location = "/errors/408.html" {
internal;
}
location = "/errors/500.html" {
internal;
}
location = "/errors/503.html" {
internal;
}
# Remove "index" from URL if requesting the front page.
location ~ "^/index(\.html)?$" {
return 301 "/";
}
# Strip .html file extension, trailing slash, or index,
# forcing the "pretty" URL, if user requests a ".html" URL.
location ~ "^/(.+)(\.html|/|/index|/index.html)$" {
return 301 "/$1";
}
[...]
}
location
ディレクティブを含むinternal
ブロックは、通常のURL処理によってエラーページが操作されるのを防ぎます。 /errors/
ディレクトリなので、internal
ディレクティブを何度も繰り返す必要はありませんが、Nginxは受信リクエストを照合してルールを書き直し、基本的にルールセレクターの具体性でソートします。各カスタムエラーページへの完全一致のみで十分でしたNginxがエラーページでURL書き換えプロセスを開始する前にエラーページを取得するための特定性。
(私のNginx専門用語の使用は少しずれているかもしれませんが、これは私には起こっているように思われます。そして、この構成は、コードコメントが言うことを正確に実行します。これは最初から望んでいたことです。)
rewrites
をlocation
ブロック内にラップすることをお勧めします。そうしないと、それらのグローバルリーチを制御することが困難になります。
この例は、質問で公開したスニペットで機能するようです:
server {
root /path/to/root;
location / {
# Remove "index" from URL if requesting the front page.
rewrite "^/index(\.html)?$" "/" permanent;
# Strip .html file extension, trailing slash, or "index.html".
rewrite "/(.+)(\.html|/|/index.html)$" "/$1" permanent;
try_files $uri $uri.html $uri/index.html =404;
}
error_page 400 /errors/400.html;
error_page 401 /errors/401.html;
error_page 403 /errors/403.html;
error_page 404 /errors/404.html;
error_page 408 /errors/408.html;
error_page 500 /errors/500.html;
error_page 503 /errors/503.html;
location /errors/ {
}
}
これは難しいことでしたが、最終的にこれは要求どおりに機能します。
server {
[...]
root /path/to/root;
set $docroot "/path/to/root";
error_page 400 /errors/400.html;
error_page 401 /errors/401.html;
error_page 403 /errors/403.html;
error_page 404 /errors/404.html;
error_page 408 /errors/408.html;
error_page 500 /errors/500.html;
error_page 503 /errors/503.html;
location = /errors/404.html {
root $docroot;
internal;
}
location ~ ^/index(\.html)?$
{
return 301 "/";
break;
}
location ~ ^/$
{
try_files $uri $uri.html $uri/index.html =404;
break;
}
location ~ ^/(.+)(\.html|/|/index.html)$
{
if (-f $docroot/$1) {
return 301 "/$1";
break;
}
if (-f $docroot/$1.html) {
return 301 "/$1";
break;
}
if (-f $docroot/$1/index.html) {
return 301 "/$1";
break;
}
try_files missing_file =404;
}
location ~ ^/(.+)(?!(\.html|/|/index.html))$
{
try_files $uri $uri.html $uri/index.html =404;
}
[...]
}
後でコメントを付けて、これを拡張してみます;)