Làm cách nào để thiết lập trang lỗi dự phòng trong nginx?


10

Tôi đang định cấu hình xử lý nginx của một số trang lỗi và các tệp phương tiện "mặc định" khác (chẳng hạn như favicon.ico và robot.txt) vào lúc này và tôi gặp phải một vấn đề nhỏ khiến mọi thứ hoạt động theo cách tôi muốn cho một số trang lỗi nhất định .

Về cơ bản, những gì tôi đang cố gắng làm là phục vụ một số tệp nhất định cho một máy chủ dưới quyền root cho máy chủ đó, ví dụ: /var/www/someserver.com/robots.txt. Nếu tệp đó không tồn tại, tôi muốn nginx đi đến "mặc định", tức là /var/www/default/robots.txt. Đây là ý chính cơ bản về cách tôi đã cấu hình (thành công):

server {
    ...
    root /var/www/someserver.com;

    location ~* ^/(robots\.txt)$ {
        error_page 404 = @default;
    }

    location @default {
        root /var/www/default;
    }
}

Điều đó làm việc tuyệt vời.

Tôi đang cố gắng làm điều tương tự cho các trang lỗi và tôi không thể làm điều đó xảy ra:

server {
    ...
    root /var/www/someserver.com;

    error_page 404   /404.html;

    location ~* ^/(404\.html)$ {
        error_page 404 = @default;
    }

    location @default {
        root /var/www/default;
    }
}

Lưu ý rằng "hoạt động" này theo nghĩa là nếu bạn truy cập someserver.com/404.html, trước tiên, nó sẽ cố tải /var/www/someserver.com/404.html và sau đó quay lại / var / www / default /404.html nếu không tìm thấy. Tuy nhiên, nếu bạn truy cập someserver.com/blahblah, nó chỉ hiển thị trang 404 nếu được đặt trong /var/www/someserver.com/. Nó không rơi trở lại thư mục mặc định nếu tập tin đó không tồn tại.

Dù sao đi nữa, bạn có thể có thể những gì tôi đã cố gắng thực hiện (đó là lý do tại sao tôi bao gồm ví dụ làm việc đầu tiên).

Có ý kiến ​​gì không?

Biên tập:

Dựa trên câu trả lời của Martin F, đây là những gì tôi đã kết hợp lại với nhau:

# Doesn't work when error page is returned on a POST request
server {
    ...
    root /var/www/someserver.com;

    error_page  404         = @notfound;
    error_page  500 502 504 = @server_error;
    error_page  503         = @maintenance;

    location @notfound {
        try_files /404.html /../default/404.html =404;
    }

    location @server_error {
        try_files /500.html /../default/500.html =500;
    }

    location @maintenance {
        try_files /503.html /../default/503.html =503;
    }
}

Điều này làm việc tuyệt vời. Khối error_pages và vị trí thực tế ở trên nằm trong tệp server_defaults.conf được bao gồm với mọi máy chủ ảo, đó là lý do tại sao tôi không mã hóa đường dẫn vào từng vị trí và sử dụng đường dẫn tương đối cho các mặc định.

Chỉnh sửa 2:

Cách tiếp cận này có một vấn đề. Nếu bạn POST đến một URL trả về lỗi, phương thức yêu cầu POST sẽ được gửi với các lần thử try_files. Điều này (đối với tôi) dẫn đến lỗi 405 Không được phép, vì về cơ bản nginx đang cố gắng POST để ví dụ /default/500.html thay vì chỉ nhận trang đó.

Chỉnh sửa 3:

Tôi đã đăng một giải pháp hoạt động gần với ý tưởng ban đầu của tôi hơn.

Câu trả lời:


10

Tôi cuối cùng đã đi với một cái gì đó rất gần với ý tưởng ban đầu của tôi. Chìa khóa tôi bị thiếu hóa ra là chỉ thị recursive_error_pages. Tất cả những gì tôi thực sự phải làm là bật "bật" này và ý tưởng ban đầu của tôi đã có hiệu quả. Đây là phần có liên quan của conf của tôi bây giờ:

server {
    ...

    root /var/www/someserver.com/;

    error_page 400 404      /404.html;
    error_page 500 502 504  /500.html;
    error_page 503          /503.html;

    recursive_error_pages   on;

    location ~* ^/(404\.html|500\.html|503\.html)$ {
        log_not_found off;
        error_page 404 = @default;
    }

    location @default {
        log_not_found on;
        root /var/www/default;
    }
}

Tôi đã bao gồm các loại lỗi khác không phải là một phần của câu hỏi ban đầu của tôi ở đây bởi vì đây là điều khiến tôi gặp khó khăn với cách tiếp cận của Martin F, điều này rất tuyệt vời. Lệnh log_not_foundnày chỉ đảm bảo rằng tôi không nhận được 404 trong nhật ký của mình khi không tìm thấy trang lỗi trong thư mục gốc.


Điều này hoạt động rất tốt (đặc biệt là kết hợp 404 / POST) nhưng dường như nuốt mã lỗi HTTP và gửi 200 ... Bạn có hành vi tương tự như tôi không?
Tháng Mười

2
Bạn có thể muốn loại bỏ log_not_found off;và thêm internal;vào thay thế.
Alix Axel

Vấn đề bạn nhận thấy với yêu cầu POST dẫn đến lỗi là hành vi kỳ lạ của nginx, xem trac.nginx.org/nginx/ticket/824
Robo

5

try_files là cách để đi đến đây. Cấu hình sau sẽ hoạt động, nhưng tôi chưa kiểm tra lỗi cú pháp.

server {
    ...
    root /var/www;

    location / {
        try_files /someserver.com$uri /default$uri /someserver.com$uri/ /default$uri/ @notfound;
    }

    location @notfound {
       try_files /someserver/404.html /default/404.html =404; # =404 should make it use the nginx-default 404 page.
    }
}

Vâng, đó chính xác là những gì tôi cần. Tôi đã thử sử dụng try_files nhưng câu trả lời của bạn khiến tôi nhận ra rằng tôi cần tạo một vị trí nội bộ đặc biệt cho nó. Tôi đã chỉnh sửa câu trả lời của mình để hiển thị cấu hình phù hợp với tôi, có một vài điều chỉnh so với những gì bạn đề xuất.
Jim D

Xem chỉnh sửa của tôi 2 ở trên. Từ những gì tôi có thể nói, đề xuất này không hoạt động với các yêu cầu POST. Vì try_files sử dụng phương thức yêu cầu của yêu cầu ban đầu, bạn kết thúc với phản hồi 405 Không được phép.
Jim D

@JimD: Vâng, bạn không chính xác sử dụng phương pháp này, bạn sử dụng một phương pháp sửa đổi. Điều này làm việc cho tôi. Hãy thử nâng cấp nhị phân Nginx của bạn nếu nó cũ hơn 0.8.x
Martin Fjordvald

Chà, vấn đề là tôi đang sử dụng cái này không chỉ cho 404, đó là lý do tại sao tôi phải làm error_page -> location -> try_files thay vì location -> try_files -> location -> try_files như bạn. Tuy nhiên, tôi là một tệp nhị phân 0,7.x từ một gói, vì vậy tôi sẽ thử xây dựng nó từ nguồn và xem liệu nó có giải quyết được nó không.
Jim D

2

Thật không may, tôi chậm trễ vài năm với câu trả lời của mình, nhưng tôi nghĩ nó có thể giúp những người tìm kiếm trong tương lai. Phiên bản Nginx đã cài đặt của tôi là 1.2.4 và tôi đã tạo đoạn mã cấu hình sau,

server {

server_name www.example.com
root /var/www/example


## Errors -> Locations
error_page   400 /400.html;
error_page   403 /403.html;
error_page   404 /404.html;
error_page   500 502 503 504 /50x.html;

## Locations -> Fallback
location = /400.html {
    try_files /400.html @error;
    internal;
}
location = /403.html {
    try_files /403.html @error;
    internal;
}
location = /404.html {
    try_files /404.html @error;
    internal;
}
location = /50x.html {
    try_files /50x.html @error;
    internal;
}

## Fallback Directory
location @error {
    root /var/www/error;
}

}

1
Sử dụng tốt internal.
Clint Pachl

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.