web-dev-qa-db-ja.com

Nginx-error_pageの書き換えを無効にする方法

現在、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がやっていることです:

  1. クライアントリクエスト/fake-page
  2. /fake-page/fake-page.html、または/fake-page/index.htmlを検索します。
  3. それらのいずれも一致しない場合、内部的にリダイレクトしてエラー404ページを表示します。
  4. ただし、/errors/404.htmlpermanentフラグを使用して.htmlを取り除き、301ユーザーリダイレクトを引き起こします。

私はその最後のrewrite行でいくつかのバリエーションを試しましたが、それをlocation ^~ /errors/ {}ブロックに入れました(これはと思います書き換えは、/-errors /ディレクトリの下にあるされないのURLにのみ適用されることを意味します)。しかし、私が行ったすべてのことにより、404ページに永続的にリダイレクトするエラー404が発生し、実際の404ステータスは返されません---またはリダイレクトループでスタックします。

2
user292113

@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専門用語の使用は少しずれているかもしれませんが、これは私には起こっているように思われます。そして、この構成は、コードコメントが言うことを正確に実行します。これは最初から望んでいたことです。)

0
user292113

rewriteslocationブロック内にラップすることをお勧めします。そうしないと、それらのグローバルリーチを制御することが困難になります。

この例は、質問で公開したスニペットで機能するようです:

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/ {
    }
}
1
Richard Smith

これは難しいことでしたが、最終的にこれは要求どおりに機能します。

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

    [...]
}

後でコメントを付けて、これを拡張してみます;)

0
Anubioz