301 vs 302 trong .htaccess | Snippet ngắn chọn đúng mã redirect【2026】
Một quy tắc: URL không quay lại → 301. URL sẽ mở lại sau bảo trì / campaign → 302. Viết snippet ngắn, kiểm bằng curl -I, đừng đoán theo cảm giác trình duyệt. Cần sinh nhanh mà ít gõ tay → htaccess generator (chọn 301 vĩnh viễn hoặc 302 tạm thời).
Developer Việt hay search “301 vs 302” khi đang sửa .htaccess lúc 11 giờ đêm — cần câu trả lời ngắn + đoạn code copy được, không cần checklist migrate domain dài. Bài này đúng góc đó: chọn mã, dán snippet, đọc header.
(Nếu bạn đang bàn giao cả project chuyển hosting/domain, đọc thêm bài migrate riêng; ở đây chỉ tập trung 301 ↔ 302 + cú pháp.)
Bảng quyết định 30 giây
| Tiêu chí | 301 Moved Permanently | 302 Found |
|---|---|---|
| Ý nghĩa | Chuyển vĩnh viễn | Chuyển tạm thời |
| Ví dụ | Đổi slug blog, gộp trang, http→https cố định | Bảo trì 2 ngày, landing sale 1 tuần |
| SEO (thực tế) | Tín hiệu thường theo URL mới | Index hay giữ URL cũ lâu hơn |
| Cache trình duyệt | Cache redirect khá dai | Cũng cache — vẫn nên test bằng curl |
| Khi nào đổi mã | Đã chắc không quay lại path cũ | Hết tạm → đổi thành 301 |
Hai lỗi ngắn hay gặp
- Dùng 302 “cho chắc” khi đã đổi slug vĩnh viễn — Google chậm chuyển xếp hạng, Search Console vẫn thấy URL cũ.
- 301 trang A→B rồi B→A — vòng lặp; trình duyệt báo ERR_TOO_MANY_REDIRECTS.
Snippet 1: một path (đủ dùng 80% case)
Đặt gần đầu file .htaccess (thường trong public_html):
# Vĩnh viễn: /khuyen-mai-cu → trang mới
Redirect 301 /khuyen-mai-cu.html https://example.com/dich-vu/
# Tạm thời: trang bảo trì
Redirect 302 / https://example.com/bao-tri.html
Lưu ý: URL đích nên là URL tuyệt đối (có https://). Path nguồn bắt đầu bằng /.
Khi nào đủ Redirect? Khi map 1-1 cố định. Không cần RewriteEngine cho việc này.
Snippet 2: RewriteRule khi cần điều kiện
RewriteEngine On
# Chỉ redirect đúng host apex → www (301)
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
# Tạm: toàn site về /coming-soon (302) — nhớ tắt sau campaign
# RewriteRule ^(.*)$ /coming-soon.html [R=302,L]
Cờ quan trọng:
| Cờ | Nghĩa |
|---|---|
R=301 / R=302 | Mã HTTP trả về |
L | Dừng rule tiếp theo (Last) |
NC | Không phân biệt hoa thường trên điều kiện Host |
Cấm copy mù: một số bài cũ chèn khoảng trắng sai kiểu % {HTTP_HOST} → Apache 500 ngay. Phải là %{HTTP_HOST}.
Snippet 3: http → https (gần như luôn 301)
Ép HTTPS là thay đổi cố định, gần như không bao giờ “tạm”:
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
Dùng 302 cho http→https chỉ làm cache / SEO rối — trừ khi bạn đang test rất ngắn trên staging.
Kiểm tra thật bằng curl (đừng tin mỗi F5)
curl -I https://example.com/khuyen-mai-cu.html
Kết quả kỳ vọng:
HTTP/1.1 301 Moved Permanently
Location: https://example.com/dich-vu/
Hoặc với 302:
HTTP/1.1 302 Found
Location: https://example.com/bao-tri.html
Checklist đọc header:
- Status đúng 301 hoặc 302?
Locationđúng URL cuối (không thiếuhttps, không thiếu/)?- Có hai lần redirect không cần thiết (http→https→www→path) khiến chậm không?
Trình duyệt cache redirect rất dai — dùng cửa sổ ẩn danh hoặc curl để khỏi tự lừa mình.
Case: junior sửa slug bài blog
Trước: https://shop.vn/blog/huong-dan-cu
Sau: https://shop.vn/blog/huong-dan-moi
Junior thêm:
Redirect 302 /blog/huong-dan-cu https://shop.vn/blog/huong-dan-moi
Hai tuần sau Search Console vẫn ưu tiên URL cũ. Đổi thành 301, curl -I xác nhận, đợi vài ngày tín hiệu chuyển. Bài học: slug đổi xong = 301, không phải 302.
Sinh snippet nhanh trên trình duyệt
Không muốn gõ tay RewriteCond? Mở htaccess generator, chọn 301 (Vĩnh viễn) hoặc 302 (Tạm thời), copy output, paste vào .htaccess đã backup.
🚀 Tạo .htaccess ngay tại đây
Công cụ chạy trên trình duyệt — phù hợp khi bạn đang ngồi hosting panel và cần đoạn rule sạch trước khi upload. Sau khi dán, vẫn chạy curl -I trên URL thật.
Mini checklist trước khi đóng ticket
- Đã chọn 301 hay 302 có lý do viết được một câu?
- Đã backup
.htaccess? - Snippet không có khoảng trắng lỗi trong
%{...}? -
curl -Ira đúng status +Location? - Nếu rule tạm (302): đã ghi reminder ngày tắt / đổi 301?
Khi nào đọc bài dài hơn?
Bài này dừng ở mã + snippet + verify. Còn chuỗi migrate domain (www↔apex, Cloudflare vs panel, bàn giao khách) thuộc checklist riêng — đừng nhồi mọi thứ vào một file .htaccess copy từ blog nước ngoài.
Nhớ câu chốt: vĩnh viễn → 301, tạm → 302, luôn đọc header bằng curl.