Tiếng Việt

Công cụ dành cho nhà phát triển · Bộ mã hóa và giải mã URL

Cách mã hóa phần trăm hoạt động: từ ký tự đến UTF-8 byte đến %XX chuỗi

· Cách thức hoạt động

url-encoding utf-8 percent-encoding nhà phát triển

Mã ký tự được ánh xạ qua các bước mã hóa UTF-8 thành chuỗi hex được mã hóa phần trăm
Hình minh họa vector ToolAcre gốc

Mã hóa phần trăm không mã hóa ký tự; nó mã hóa byte. Bài đăng này cho biết cách một ký tự trở thành UTF-8 byte, sau đó là các cặp hex và tại sao một chữ cái có dấu lại có hai nhóm %XX trong khi biểu tượng cảm xúc lại có bốn nhóm.

Tại sao 'é' biến thành %C3%A9 thay vì %E9 — quan sát cho thấy lớp byte bên dưới

Khi nhà phát triển cấp dưới nhìn thấy %C3%A9 trong URL, mã hóa phần trăm hoạt động trên byte chứ không phải ký tự. Ký tự é không phải là một byte; UTF-8 mã hóa thành hai: C3 A9. Quy tắc mã hóa phần trăm từ RFC 3986 rất đơn giản: mã hóa từng byte dưới dạng dấu phần trăm, theo sau là hai chữ số thập lục phân. Sự khác biệt đó chuyển lời giải thích từ bí ẩn sang hợp lý.

Để hiểu mã hóa phần trăm đòi hỏi phải hiểu UTF-8. Văn bản phải được chuyển đổi thành byte bằng cách sử dụng mã hóa ký tự. UTF-8 là tiêu chuẩn cho URL và web. Nó biểu thị các ký tự dưới dạng chuỗi byte có độ dài thay đổi: ASCII sử dụng một byte, chữ cái có dấu sử dụng hai byte, biểu tượng cảm xúc sử dụng bốn byte. Mỗi giai đoạn đều khác nhau: ký tự, điểm mã Unicode, UTF-8 byte, sau đó là %XX cặp. Chuyển sang hex mà không hiểu byte sẽ bỏ lỡ điểm.

Quy tắc mã hóa phần trăm từ RFC 3986 - một % theo sau là hai chữ số hex trên mỗi byte, ưu tiên chữ hoa

RFC 3986 xác định một quy tắc: mã hóa từng byte dưới dạng phần trăm theo sau là hai chữ số thập lục phân viết hoa. Các ký tự không được đặt trước không cần mã hóa là các chữ cái, chữ số, dấu gạch nối, dấu gạch dưới, dấu chấm và dấu ngã. Mọi thứ khác phải được mã hóa. Dấu cách trở thành %20, dấu gạch chéo trở thành %2F và dấu phần trăm trở thành %25. Điều này ngăn các ký tự đặc biệt trong giá trị truy vấn phá vỡ cấu trúc URL.

Khoảng trắng mã hóa thành byte 0x20, trở thành %20. Dấu gạch chéo lên là 0x2F, trở thành %2F. Đây là ASCII ký tự cần một byte. Chữ cái có dấu và biểu tượng cảm xúc khác nhau. Dấu phần trăm trở thành %25. Các dấu phân cách dành riêng như dấu hai chấm được mã hóa để bảo toàn cấu trúc. Điều này ngăn không cho ký hiệu và hoặc bằng được nhúng trong tham số truy vấn phá vỡ quá trình phân tích cú pháp. Mỗi byte trở thành %HH.

UTF-8 làm bộ ký tự giả định — tại sao các URL hiện đại là UTF-8 và nơi có các ngoại lệ cũ

UTF-8 sử dụng mã hóa có độ dài thay đổi. ASCII từ điểm mã 0 đến 127 là một byte. Các ký tự từ 128 đến 2047, bao gồm các chữ cái Latinh có dấu, là hai byte. Các ký tự từ 2048 đến 65535, phổ biến trong chữ viết Đông Á, có kích thước ba byte. Các ký tự trên 65535, bao gồm hầu hết các biểu tượng cảm xúc, có kích thước 4 byte. Mỗi byte có tiền tố là các bit báo hiệu có bao nhiêu byte theo sau.

Chữ é có dấu là mã Unicode U+00E9. UTF-8 mã hóa thành hai byte: 0xC3 và 0xA9. Mã hóa phần trăm tạo ra %C3%A9. Tiếng Đức ü (U+00FC) mã hóa thành 0xC3 0xBC, trở thành %C3%BC. Tiếng Tây Ban Nha ñ (U+00F1) mã hóa thành 0xC3 0xB1, trở thành %C3%B1. Mẫu này nhất quán: byte đầu tiên báo hiệu một chuỗi hai byte. Một chữ cái có dấu sẽ mở rộng thêm sáu ký tự trong bảng mã.

Ví dụ hoạt động: mã hóa 'café 😀' byte theo byte — các điểm mã, UTF-8 byte và chuỗi kết quả

Biểu tượng cảm xúc làm cho lớp byte trở nên rõ ràng. Biểu tượng cảm xúc thích 👍 là mã điểm U+1F44D. UTF-8 mã hóa thành bốn byte: F0 9F 91 8D. Mã hóa phần trăm tạo ra %F0%9F%918D: mười hai ký tự cho một ký hiệu. Mặt cười 😀 (U+1F600) mã hóa thành F0 9F 98 80, trở thành %F0%9F%9880. Chuỗi bốn byte trở thành ký tự được mã hóa mười hai phần trăm.

Văn bản hỗn hợp cho thấy tại sao việc hiểu byte lại quan trọng. Cụm từ "café 😀" chỉ chứa ASCII đơn giản, một dấu và một biểu tượng cảm xúc. Các chữ cái c, a, f mã hóa thành 63, 61, 66. é mã hóa là C3 A9. Không gian mã hóa thành 20. Biểu tượng cảm xúc mã hóa thành F0 9F 98 80. Kết quả là "caf%C3%A9%20%F0%9F%9880". Việc hiểu byte nào cần mã hóa sẽ giúp kết quả đầu ra có thể dự đoán được.

Giải mã ngược lại — thu thập các nhóm %XX thành byte và chỉ sau đó diễn giải chúng dưới dạng UTF-8

Giải mã đảo ngược quá trình. Bộ giải mã quét các cặp %XX và thu thập chúng thành các giá trị byte. Nhìn thấy %C3%A9, nó trích xuất byte C3 và A9. Giải mã UTF-8 diễn giải những ký tự đó dưới dạng ký tự é. Nếu một chuỗi không đầy đủ, chẳng hạn như chỉ %C3, kết quả sẽ là lỗi. Bộ giải mã biết từ các bit tiền tố UTF-8 rằng C3 yêu cầu byte thứ hai.

Chữ số hex không quan trọng; %C3%A9 và %c3%a9 giải mã giống hệt nhau. RFC cho phép viết hoa hoặc viết thường, mặc dù chữ hoa được ưu tiên hơn. Nhưng vấn đề về chữ hoa chữ thường đối với các ký tự: é (dưới dạng %C3%A9) không giống với É (dưới dạng %C3%89). URL so sánh phải bình thường hóa mã hóa phần trăm hoặc có nguy cơ coi các tài nguyên giống hệt nhau là khác nhau. Các khung bình thường hóa trước khi lưu vào bộ nhớ đệm.

Tại sao chữ hoa chữ thường không quan trọng ở các chữ số hex nhưng lại quan trọng ở nơi khác — quy tắc chuẩn hóa và so sánh URL

RFC 3986 đề cập đến punycode cho tên miền và mã hóa biểu mẫu để gửi dưới dạng quy tắc riêng biệt. Punycode mã hóa các tên miền không phải ASCII mà không có dấu phần trăm cho khả năng tương thích DNS. Miền 😀.example trở thành "xn--js8h.example". Mã hóa biểu mẫu sửa đổi mã hóa phần trăm với một ngoại lệ: dấu cách trở thành dấu cộng thay vì %20. Các biểu mẫu đã gửi dưới dạng đơn đăng ký/x-www-form-urlencoded sử dụng dấu cộng cho khoảng trắng.

Công cụ mã hóa URL hiển thị cả ba chế độ: mã hóa thành phần, mã hóa toàn bộURL và mã hóa biểu mẫu. Mã hóa thành phần với EncodeURIComponent mã hóa mọi ký tự đặc biệt bao gồm cả dấu phân cách, phù hợp với các giá trị truy vấn. Mã hóa toàn bộURL bằng mã hóaURI giữ nguyên các ký tự cấu trúc cho các URL hoàn chỉnh. Mã hóa biểu mẫu dành cho nội dung POST. Mỗi lần sử dụng UTF-8; chúng chỉ khác nhau ở chỗ byte không được mã hóa.

Mã hóa Punycode và biểu mẫu: tiêu chuẩn anh chị em, không phải phần mở rộng mã hóa phần trăm

Phối cảnh byte giải quyết những bí ẩn URL. Tại sao một biểu tượng cảm xúc cần mười hai ký tự? Bởi vì UTF-8 sử dụng bốn byte, mỗi byte trở thành %HH. Tại sao một số URL có %2F dấu gạch chéo trong khi các URL khác có dấu gạch chéo đơn giản? Bởi vì chế độ mã hóa quyết định: dấu gạch chéo trong đoạn đường dẫn vẫn không được mã hóa nhưng bên trong giá trị truy vấn phải là %2F để tránh đọc sai.

Hãy suy nghĩ theo byte để có thể dự đoán mã hóa phần trăm. Một ký tự là một điểm mã Unicode. UTF-8 là biểu diễn byte của nó. Mã hóa phần trăm là định dạng truyền tải. Việc mở rộng ký tự diễn ra ở lớp UTF-8. Trường hợp hex không ảnh hưởng đến việc giải mã nhưng trường hợp ký tự thì có. Chuỗi byte không hợp lệ không thành công ở UTF-8 do quy tắc tiền tố nghiêm ngặt. Công cụ mã hóa URL hiển thị tiến trình này.

Bài học rút ra: tính theo byte — cách bộ mã hóa và giải mã URL hiển thị kết quả đầu ra %XX chính xác cho bất kỳ văn bản nào bạn dán trong trình duyệt

Ví dụ hoạt động: mã hóa "café 😀". Từ café có các chữ cái c, a, f dưới dạng ASCII byte đơn: 63, 61, 66. é là UTF-8 hai byte: C3 A9. Không gian là 20. Biểu tượng cảm xúc 😀 có bốn byte: F0 9F 98 80. Các chữ cái ASCII không được đặt trước vẫn hiển thị. Kết quả: "caf%C3%A9%20%F0%9F%9880". Điều này cho thấy lý do tại sao một biểu tượng cảm xúc lại mở rộng thành 12 ký tự.

Takeaway: suy nghĩ bằng byte, không phải ký tự. Mã hóa phần trăm được áp dụng sau mã hóa UTF-8. Mỗi byte trở thành %HH. Độ dài thay đổi UTF-8 nghĩa là các ký tự mở rộng khác nhau: ASCII trở thành %XX (hai ký tự), dấu hai byte trở thành %XX%XX (sáu ký tự), biểu tượng cảm xúc bốn byte trở thành %XX%XX%XX%XX (mười hai ký tự). Dán văn bản vào công cụ mã hóa URL và quan sát tiến trình.