Nginx

Nginx - 如何禁用error_page的重寫

  • February 16, 2017

我目前在 Fedora 25 Server Edition x86_64 上使用 Nginx 1.10.2 託管幾個小型靜態網站。

我已將 Nginx 配置為假設.html沒有文件副檔名 ( try_files) 的 for 請求,並在請求時將 (永久rewrite) 重定向到.htmlURL 的 -less 版本.*\.html

我也有自定義錯誤頁面。據我目前所知,該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;

   [...]
}

以下是我認為Nginx 正在做的事情:

  1. 客戶請求/fake-page
  2. 查找/fake-page,/fake-page.html/fake-page/index.html.
  3. 當這些都不匹配時,內部重定向以顯示錯誤 404 頁面。
  4. 但隨後/errors/404.html被帶標誌的 .html 剝離permanent ,導致 301 使用者重定向。

我在最後rewrite一行嘗試了幾種變體,甚至將它放在一個location ^~ /errors/ {}塊中(我認為這應該意味著重寫只適用於不在/errors/ 目錄下的 URL)。但是我所做的一切都導致錯誤 404 永久重定向到 404頁面,然後它不會返回實際的 404 狀態 —或者它最終陷入重定向循環。

我建議您將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;    
   }

   [...]
}

我稍後會嘗試用評論來擴展它;)

引用自:https://serverfault.com/questions/832086