วิธีการตั้งค่าหน้าข้อผิดพลาดทางเลือกใน nginx?


10

ฉันกำลังกำหนดค่าการจัดการ nginx ของหน้าข้อผิดพลาดบางอย่างและไฟล์สื่อ "เริ่มต้น" อื่น ๆ (เช่น favicon.ico และ robots.txt) ในขณะนี้และฉันพบปัญหาเล็กน้อยเพื่อให้สิ่งต่าง ๆ ทำงานตามที่ฉันต้องการสำหรับหน้าข้อผิดพลาดบางอย่าง .

โดยทั่วไปสิ่งที่ฉันพยายามทำคือให้บริการไฟล์บางอย่างสำหรับเซิร์ฟเวอร์ภายใต้รูทสำหรับเซิร์ฟเวอร์นั้นเช่น /var/www/someserver.com/robots.txt หากไฟล์นั้นไม่มีอยู่ฉันต้องการให้ nginx ไปที่ "default" เช่น /var/www/default/robots.txt นี่เป็นส่วนสำคัญพื้นฐานของวิธีการตั้งค่า (สำเร็จ):

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

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

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

มันใช้งานได้ดีมาก

ฉันพยายามทำเช่นเดียวกันสำหรับหน้าข้อผิดพลาดและฉันไม่สามารถทำสิ่งนั้นได้แม้ว่า:

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

    error_page 404   /404.html;

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

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

โปรดทราบว่า "ใช้งานได้" ในแง่ที่ว่าหากคุณเข้าชม someserver.com/404.html อันดับแรกจะพยายามโหลด /var/www/someserver.com/404.html ก่อนจากนั้นถอยกลับไปที่ / var / www / default /404.html หากไม่พบ อย่างไรก็ตามหากคุณเข้าชม someserver.com/blahblah จะแสดงเฉพาะหน้า 404 หากตั้งไว้ที่ /var/www/someserver.com/ มันจะไม่ถอยกลับไปยังไดเรกทอรีเริ่มต้นหากไฟล์นั้นไม่มีอยู่

อย่างไรก็ตามคุณสามารถสิ่งที่ฉันพยายามที่จะบรรลุ (นั่นคือเหตุผลที่ฉันรวมตัวอย่างการทำงานแรก)

ความคิดใด ๆ

แก้ไข:

จากคำตอบของ Martin F นี่คือสิ่งที่ฉันลงเอยด้วยกัน:

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

มันใช้งานได้ดี บล็อกที่เกิดขึ้นจริงของ error_pages และตำแหน่งด้านบนนั้นอยู่ในไฟล์ server_defaults.conf ที่รวมอยู่กับโฮสต์เสมือนทุกตัวซึ่งเป็นสาเหตุที่ฉันไม่ได้ใส่รหัสเส้นทางในแต่ละตำแหน่งและใช้เส้นทางสัมพัทธ์เป็นค่าเริ่มต้น

แก้ไข 2:

วิธีนี้มีปัญหา หากคุณโพสต์ไปที่ URL ที่ส่งคืนข้อผิดพลาดเมธอดคำขอ POST จะถูกส่งไปพร้อมกับความพยายาม try_files (สำหรับฉัน) นี้ทำให้เกิดข้อผิดพลาด 405 Not Allowed เนื่องจาก nginx พยายามโพสต์เป็นหลักเช่น /default/500.html แทนที่จะเพิ่งได้รับหน้านั้น

แก้ไข 3:

ฉันโพสต์โซลูชันที่ใช้งานได้ใกล้เคียงกับแนวคิดดั้งเดิมของฉันมาก

คำตอบ:


10

ฉันลงเอยด้วยบางสิ่งที่ใกล้เคียงกับความคิดดั้งเดิมของฉัน recursive_error_pagesฉันสำคัญที่ขาดหายไปเปิดออกมาเป็นคำสั่ง สิ่งที่ฉันต้องทำก็แค่เปิด "สิ่งนี้" และความคิดดั้งเดิมของฉันก็ใช้ได้ นี่คือสิ่งที่ส่วนที่เกี่ยวข้องในความเชื่อมั่นของฉันดูเหมือนตอนนี้:

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

ฉันรวมประเภทข้อผิดพลาดอื่น ๆ ที่ไม่ได้เป็นส่วนหนึ่งของคำถามดั้งเดิมของฉันที่นี่เพราะนี่คือสิ่งที่ทำให้ฉันมีปัญหากับวิธีการของ Martin F ซึ่งยอดเยี่ยมมาก log_not_foundสั่งเพียงเพื่อให้แน่ใจว่าฉันไม่ได้รับ 404 ในบันทึกของฉันเมื่อหน้าข้อผิดพลาดที่ไม่ได้พบในรากเดิม


มันใช้งานได้ดี (โดยเฉพาะชุด 404 / POST) แต่ดูเหมือนจะกลืนรหัสข้อผิดพลาด HTTP และส่ง 200 ... คุณมีพฤติกรรมเช่นเดียวกับที่ฉันทำหรือไม่?
ต.ค.

2
คุณอาจต้องการลบlog_not_found off;และเพิ่มinternal;แทน
Alix Axel

ปัญหาที่คุณสังเกตเห็นด้วยคำขอ POST ที่ทำให้เกิดข้อผิดพลาดคือพฤติกรรมแปลก ๆ โดย nginx ให้ดูที่trac.nginx.org/nginx/ticket/824
Robo

5

try_filesเป็นวิธีที่จะไปที่นี่ การกำหนดค่าต่อไปนี้ควรใช้งานได้ แต่ฉันไม่ได้ทดสอบเพื่อหาข้อผิดพลาดทางไวยากรณ์

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

ใช่นั่นคือสิ่งที่ฉันต้องการ ฉันลองใช้ try_files แต่คำตอบของคุณทำให้ฉันรู้ว่าฉันต้องสร้างตำแหน่งภายในพิเศษสำหรับมัน ฉันได้แก้ไขคำตอบของฉันเพื่อแสดงการกำหนดค่าที่เหมาะกับฉันซึ่งมีการปรับแต่งเล็กน้อยตามที่คุณแนะนำ
Jim D

ดูการแก้ไขของฉัน 2 ด้านบน จากสิ่งที่ฉันสามารถบอกได้ข้อเสนอแนะนี้ไม่ทำงานกับคำขอ POST เนื่องจาก try_files ใช้วิธีการร้องขอของคำขอต้นฉบับคุณจะได้รับการตอบกลับที่ไม่อนุญาต 405
Jim D

@JimD: คุณไม่ได้ใช้วิธีการนี้อย่างแน่นอนคุณใช้วิธีการแก้ไข มันใช้งานได้สำหรับฉัน ลองอัปเกรดไบนารี Nginx ของคุณหากเก่ากว่า 0.8.x
Martin Fjordvald

ปัญหาคือฉันใช้สิ่งนี้มานานกว่า 404 วินาทีซึ่งเป็นสาเหตุที่ฉันต้องทำ error_page -> location -> try_files แทนที่จะเป็น location -> try_files -> location -> try_files อย่างที่คุณเป็น อย่างไรก็ตามฉันอยู่ในไบนารี 0.7.x จากแพ็คเกจดังนั้นฉันจะลองสร้างมันจากแหล่งที่มาและดูว่ามันแก้ได้ไหม
Jim D

2

น่าเสียดายที่ฉันมีคำตอบไม่กี่ปีที่ผ่านมา แต่ฉันคิดว่ามันอาจช่วยผู้ค้นหาในอนาคตได้ เวอร์ชัน Nginx ที่ติดตั้งของฉันคือ 1.2.4 และฉันได้สร้างตัวอย่างข้อมูลการกำหนดค่าต่อไปนี้

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
internalการใช้งานที่ดีของ
Clint Pachl

0

ฉันพบว่าเป็นเรื่องสำคัญที่จะต้องรวม "proxy_intercept_errors on" ในบล็อกตำแหน่งใด ๆ ที่มี error_page รวมอยู่ด้วย

หากไม่มีการตั้งค่านี้บล็อกสถานที่จะตัดรหัสข้อผิดพลาดกลับมาจากอัปสตรีม

http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_intercept_errors

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.