Lỗi Gặp Phải
Bạn gửi một POST request — từ form, fetch(), hoặc curl — và Nginx trả về:
405 Method Not Allowed
Response headers bao gồm:
Allow: GET, HEAD
Backend của bạn không bao giờ nhận được request. Nginx chặn nó từ trước.
Nguyên Nhân Gốc Rễ
Module file tĩnh của Nginx (ngx_http_static_module) chỉ xử lý GET và HEAD. Khi một POST request trúng vào location block trỏ tới file trên đĩa, Nginx từ chối ngay lập tức với lỗi 405. Ứng dụng của bạn không bao giờ thấy request đó. Điều này xảy ra với cả root, alias, và try_files.
Bốn tình huống thường gặp gây ra lỗi này:
- Một form có
action="/submit"trỏ đến URL được khớp bởi mộtrootblock tĩnh - Một SPA React hoặc Vue nơi
try_files $uri /index.htmlbắt tất cả các route — bao gồm cả các API call tới backend - Thứ tự location block:
location /catch-all tĩnh khớp trước một proxy block cụ thể hơn - Một API endpoint như
/api/loginbị vô tình phục vụ như file tĩnh
Chẩn Đoán Trước
Trước khi thay đổi bất cứ điều gì, hãy tìm location block nào đang xử lý request của bạn:
sudo nginx -T | grep -A 10 "location"
Sau đó kiểm tra bằng curl và xem kết quả trả về:
curl -sv -X POST https://yourdomain.com/api/submit \
-H "Content-Type: application/json" \
-d '{"key":"value"}' 2>&1 | grep -E "&1 | grep X-Debug-Upstream
- Header có mặt kèm địa chỉ IP: lỗi 405 đến từ app server của bạn. Sửa trong ứng dụng, không phải Nginx.
- Header vắng mặt: Nginx tự sinh ra lỗi 405. Áp dụng Cách Sửa 1 hoặc Cách Sửa 2.
Kiểm Tra Sau Khi Sửa
Sau khi chỉnh sửa config, kiểm tra cú pháp và reload:
# Kiểm tra cú pháp
sudo nginx -t
# Reload không có downtime
sudo nginx -s reload
Thử lại request bị lỗi:
curl -sv -X POST https://yourdomain.com/api/submit \
-H "Content-Type: application/json" \
-d '{"test": true}'
Sửa thành công sẽ cho bạn response thực từ backend — 200, 201, hoặc thậm chí lỗi validation từ ứng dụng. Bất cứ thứ gì trừ 405. Vẫn thấy 405? Hãy chắc chắn rằng file config bạn đã chỉnh sửa thực sự được load:
sudo nginx -T | grep "include"
Phòng Ngừa
- Luôn định nghĩa các location block cụ thể trước các block chung chung. Đặt
/api/trên/trong mọi server block kết hợp file tĩnh và backend proxy. - Giữ
try_filesvà API proxying trong các block riêng biệt. Một block cho SPA fallback, một block riêng cho proxy — không có ngoại lệ. - Kiểm tra tất cả HTTP method trong môi trường staging. Một lệnh đơn giản sau mỗi lần deploy sẽ phát hiện ngay lập tức:
curl -X POST https://staging.example.com/api/health. - Theo dõi error log trong quá trình phát triển. Lỗi 405 xuất hiện trong
/var/log/nginx/error.logtrước khi bạn nhận ra trên trình duyệt:tail -f /var/log/nginx/error.log.

