Vì sao URL cần được mã hóa
URL chỉ được chứa một tập ký tự ASCII giới hạn, và nhiều ký tự trong số đó có nhiệm vụ riêng. ? mở đầu chuỗi truy vấn, & ngăn cách các tham số, = tách tên khỏi giá trị, # mở đầu phần fragment và / ngăn cách các phân đoạn đường dẫn. Nếu từ khóa tìm kiếm hay tên tệp chứa một trong những ký tự này, trình duyệt hoặc máy chủ sẽ đọc nó như cấu trúc thay vì dữ liệu.
Mã hóa phần trăm giải quyết điều này bằng cách viết ký tự gây vấn đề thành % theo sau là hai chữ số thập lục phân. Dấu cách thành %20, & thành %26, / thành %2F. Ký tự ngoài ASCII trước tiên được chuyển thành các byte UTF-8 và mỗi byte được mã hóa riêng, nên é thành %C3%A9 và một emoji đơn lẻ biến thành bốn nhóm %XX.
Những tình huống bạn cần đến nó:
- Tạo liên kết có từ khóa tìm kiếm, URL chuyển hướng hoặc địa chỉ email làm tham số.
- Đặt một URL bên trong URL khác, ví dụ giá trị
returnTohoặcredirect_uritrong luồng đăng nhập. - Gỡ lỗi webhook và liên kết phân tích đến dưới dạng một mớ
%không đọc nổi. - Đọc log máy chủ, nơi các đường dẫn được yêu cầu được ghi ở dạng đã mã hóa.
Chế độ thành phần và chế độ cả URL
Ô đánh dấu Mã hóa cả URL (giữ :/?&=) chọn giữa hai quy tắc khác nhau, và chọn sai là lỗi thường gặp nhất.
Mặc định: mã hóa một thành phần
Khi bỏ chọn ô này, mọi thứ trừ chữ cái, chữ số và - _ . ! ~ * ' ( ) đều được mã hóa. Đây là lựa chọn đúng cho một giá trị đơn lẻ sẽ đứng sau = trong chuỗi truy vấn hoặc nằm trong một phân đoạn đường dẫn. Văn bản rock & roll/live thành rock%20%26%20roll%2Flive, có thể nằm an toàn trong ?q= mà không làm hỏng danh sách tham số.
Cả URL
Khi chọn ô này, các ký tự tạo nên cấu trúc của URL được giữ lại: : / ? # & = + , ; @ $ và những ký tự liệt kê ở trên. Dấu cách, chữ cái ngoài ASCII và vài ký tự khác vẫn được mã hóa. Hãy dùng chế độ này khi bạn có một địa chỉ hoàn chỉnh gần như hợp lệ, ví dụ https://example.com/files/annual report.pdf, và chỉ cần sửa dấu cách.
Chế độ cả URL không phân biệt được & mang tính cấu trúc với & thuộc về bên trong một giá trị. Trong https://shop.example/?q=salt & pepper, dấu & được giữ nguyên và máy chủ nhận được một tham số bị hỏng. Trong trường hợp đó, hãy mã hóa riêng giá trị ở chế độ thành phần rồi dán vào URL.
Dấu cách, dấu cộng và mã hóa kép
Có hai quy ước cho dấu cách. Mã hóa đường dẫn và URL nói chung dùng %20; dữ liệu gửi từ biểu mẫu HTML (application/x-www-form-urlencoded) dùng +. Công cụ mã hóa này luôn tạo ra %20, thứ mà mọi máy chủ đều hiểu ở cả hai nơi.
Bộ giải mã chuyển + thành dấu cách trước khi giải mã, vì đó là ý nghĩa của nó trong chuỗi truy vấn dạng biểu mẫu. Tác dụng phụ: một dấu cộng thật chưa bao giờ được mã hóa, như C++ trong đường dẫn, sẽ bị giải mã thành dấu cách. Nếu văn bản gốc chứa dấu cộng thật, lẽ ra nó phải được gửi dưới dạng %2B, và dạng đó giải mã chính xác.
Mã hóa kép là cái bẫy kinh điển còn lại. Bản thân dấu % được mã hóa thành %25, nên chạy một chuỗi đã mã hóa qua bộ mã hóa thêm lần nữa sẽ biến %20 thành %2520. Nếu bạn thấy %25 theo sau là hai chữ số thập lục phân trong một liên kết không hoạt động, hãy giải mã một lần và kiểm tra kết quả.
Khi giải mã thất bại
"Chuỗi mã hóa không hợp lệ" xuất hiện khi sau % không phải là hai chữ số thập lục phân, hoặc khi các byte không tạo thành UTF-8 hợp lệ. Nguyên nhân thường gặp:
- Liên kết bị cắt cụt, đứt giữa một chuỗi
%C3%A9. - Dấu phần trăm thật, như trong
50% off, chưa bao giờ được mã hóa. - Văn bản được mã hóa từ lâu bằng bảng mã một byte cũ như Windows-1251 hay Latin-1, nơi
élà%E9thay vì%C3%A9.
Với hai trường hợp đầu, hãy sửa phần bị hỏng bằng tay. Với bảng mã cũ không có cách sửa tự động đáng tin cậy, vì cùng một byte lại mang nghĩa chữ cái khác nhau trong các bảng mã khác nhau.
Các kiểu mã hóa liên quan
Mã hóa phần trăm không giống với Base64, vốn biến các byte bất kỳ thành một chuỗi gọn, cũng không giống thực thể HTML như &, vốn dành cho văn bản bên trong HTML. Với địa chỉ dễ đọc tạo từ tiêu đề, Tạo slug URL cho kết quả sạch hơn mã hóa: My Trip to Kraków thành my-trip-to-krakow thay vì My%20Trip%20to%20Krak%C3%B3w.
Mã hóa và giải mã chạy trong trình duyệt, nên token hay tham số riêng tư bên trong URL không bị gửi đi đâu cả.