Công cụ dành cho nhà phát triển · Bộ mã hóa và giải mã URL
WHATWG URL Tiêu chuẩn so với RFC 3986: tại sao trình duyệt và thư viện không đồng ý
· Lý lịch
url-encoding tiêu chuẩn developer-tools
Có hai định nghĩa sống động về URL và chúng không đồng ý về mục đích. Bài đăng này giải thích lý do tại sao WHATWG lại viết tiêu chuẩn riêng, trong đó cả hai tiêu chuẩn này khác nhau về mã hóa và phân tích cú pháp cũng như mã của bạn tuân theo tiêu chuẩn nào.
URL mà một thư viện nghiêm ngặt từ chối và trình duyệt vui vẻ tải — một chuỗi, hai phán quyết
Một chuỗi có dấu gạch chéo ngược trong JavaScript có thể được trình duyệt của bạn diễn giải một cách trôi chảy như một phần của đường dẫn URL. Chuỗi tương tự đó đạt đến phần phụ trợ của thư viện Python và nó từ chối phân tích cú pháp vì không cho phép dấu gạch chéo ngược. Một URL, hai kết quả khác nhau. Điều đó cũng không sai – chúng tuân theo các tiêu chuẩn khác nhau. Tiêu chuẩn WHATWG mô tả những gì trình duyệt thực sự làm với URL trong thế giới thực, bao gồm cả cách chúng xử lý dữ liệu nhập không đúng định dạng. RFC 3986 xác định ngữ pháp chính thức mà URL phải tuân theo một cách lý tưởng. Nhiều thư viện phụ trợ được xây dựng trên RFC 3986 thực thi nghiêm ngặt ngữ pháp đó và từ chối mọi nội dung bên ngoài nó.
Sự khác biệt này rất quan trọng khi bạn di chuyển dữ liệu giữa các môi trường. Trình duyệt URL chấp nhận có thể không xác thực được trong công cụ phụ trợ. Việc hiểu rõ tiêu chuẩn mà mã của bạn triển khai sẽ giúp ngăn chặn việc gỡ lỗi các vấn đề ảo—URL hoạt động tốt ở một nơi nhưng lại thất bại một cách bí ẩn ở nơi khác mà không có lý do rõ ràng.
Tại sao WHATWG lại bắt đầu lại — mô tả những gì trình duyệt thực sự làm với thông tin đầu vào không đúng định dạng thay vì thông tin hợp lệ
Nhóm làm việc WHATWG được thành lập vào 2004 để chuẩn hóa cách trình duyệt thực sự xử lý URL trong thực tế, thay vì xác định các quy tắc chính thức chặt chẽ hơn mà trình duyệt sẽ không tuân theo. RFC 2396 đã mô tả một đặc tả ngữ pháp chính thức, nhưng trong thực tế, các trình duyệt không bao giờ tuân theo nó một cách chính xác. Các trình duyệt trong thế giới thực đã phát triển các quy tắc thực tế để chấp nhận khoảng trắng, xử lý các ký tự thoát và khôi phục từ dữ liệu nhập không đúng định dạng mà RFC không lường trước hoặc mong đợi.
RFC 3986 đã đến 2005 với ngữ pháp chính thức dành cho các URL được định dạng đúng và các yêu cầu nghiêm ngặt. Trình duyệt triển khai WHATWG; thư viện phụ trợ thường triển khai RFC 3986.
Bộ mã hóa so với các ký tự dành riêng — danh sách từng thành phần của Tiêu chuẩn URL liên quan như thế nào đến các danh mục của RFC 3986
RFC 3986 chia các ký tự thành ba loại: dành riêng, không đặt trước và mọi thứ khác phải được mã hóa. Các ký tự dành riêng như dấu hai chấm, dấu gạch chéo, dấu hỏi và hàm băm có ý nghĩa cấu trúc trong URL. Các ký tự không được đặt trước 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ã; những thứ này luôn an toàn. Mọi thứ khác được mã hóa phần trăm dưới dạng byte. Tiêu chuẩn đưa ra một quy tắc rõ ràng: biết nhân vật của bạn thuộc loại nào.
Tiêu chuẩn WHATWG URL áp dụng cách tiếp cận dựa trên thành phần. Nó chỉ định các quy tắc mã hóa khác nhau cho lược đồ, quyền hạn, đường dẫn, truy vấn và đoạn riêng biệt thay vì sử dụng các danh mục chung. Ký hiệu và có thể được mã hóa trong một đường dẫn nhưng vẫn được giữ nguyên trong chuỗi truy vấn. Một khoảng trắng luôn được mã hóa nhưng cách biểu diễn chính xác sẽ thay đổi tùy theo ngữ cảnh. Thiết kế theo từng thành phần này phù hợp với hành vi của trình duyệt tốt hơn nhiều nhưng yêu cầu bạn phải biết phần nào của URL mà bạn đang mã hóa.
Khả năng chịu lỗi: dấu cách, dấu gạch chéo ngược và tab - nhập một tiêu chuẩn từ chối và sửa chữa khác
Các khoảng trắng phải trở thành %20 theo cả hai tiêu chuẩn nhưng trình duyệt sẽ âm thầm chuyển đổi các khoảng trắng theo nghĩa đen. Dấu gạch chéo ngược bị cấm theo cả hai tiêu chuẩn, tuy nhiên một số trình duyệt coi chúng là dấu phân cách đường dẫn. Tab, dòng mới và ký tự điều khiển đều bị cấm. WHATWG chỉ định hành vi phân tích cú pháp nhẹ nhàng: chuyển đổi hoặc bỏ qua chúng.
Các ký tự không phảiASCII như é hoặc 中 phải được mã hóa phần trăm bằng mã hóa UTF-8. RFC 3986 không thực sự chỉ định chính bước mã hóa ký tự; nó giả sử byte tồn tại nhưng không cho biết cách lấy chúng từ văn bản. Tiêu chuẩn WHATWG yêu cầu rõ ràng UTF-8: trước tiên hãy chuyển chuỗi thành UTF-8 byte, sau đó mã hóa chúng theo phần trăm. Cả hai tiêu chuẩn đều đạt được kết quả mã hóa giống nhau, nhưng chúng bắt đầu từ các giả định cơ bản khác nhau và không rõ ràng về những điều giống nhau.
Ví dụ hoạt động: phân tích cú pháp URL bằng dấu gạch chéo ngược và dấu cách trong cả hai mô hình — kết quả đầu ra được so sánh
Lấy chuỗi ví dụ "https://example.com/café\ tìm kiếm". Trình duyệt gặp dấu gạch chéo ngược và coi đó là ký tự đường dẫn; nó nhìn thấy không gian và mã hóa nó thành %20, tạo ra thứ gì đó như https://example.com/café%5C%20search. Trình phân tích cú pháp RFC 3986 từ chối toàn bộ URL ngay lập tức vì dấu gạch chéo ngược bị cấm và dấu cách bị cấm. Trình duyệt tiếp tục phân tích cú pháp; trình phân tích cú pháp nghiêm ngặt dừng hoàn toàn. Hãy thử một ví dụ khác: "https://user@example.com:80/path?q=a&b=c". Cả hai tiêu chuẩn đều xác định rõ ràng thông tin người dùng, máy chủ, cổng, đường dẫn và truy vấn. Chúng hoàn toàn đồng ý với cấu trúc URL này. Sự bất đồng chỉ xảy ra với các đầu vào bất thường hoặc không đúng định dạng.
Mở bộ mã hóa và giải mã URL rồi so sánh chế độ RFC 3986 với hoạt động của trình duyệt. Dán một chuỗi có dấu cách, dấu gạch chéo ngược hoặc các trường hợp cạnh khác. Công cụ này hiển thị cho bạn chính xác cách mỗi tiêu chuẩn chuyển đổi cùng một đầu vào theo cách khác nhau. Bạn sẽ thấy ngay cái nào chặt chẽ hơn và mỗi cái làm gì.
Môi trường của bạn sử dụng cái nào - trình duyệt và Nút tuân theo Tiêu chuẩn URL; nhiều thư viện máy chủ tuân theo RFC, được mô tả chung
Trong trình duyệt, JavaScript sử dụng tiêu chuẩn WHATWG URL theo mặc định. URL API triển khai chính xác. Node.js cũng sử dụng WHATWG. Thư viện Python có xu hướng triển khai RFC 3986; urllib theo sát nó. Các thư viện Java khác nhau; java.net.URL có xu hướng RFC 3986. Thùng url của Rust theo sau WHATWG. Mạng của Go/url chịu ảnh hưởng của WHATWG. Đây là một mô hình chung, không phải là một quy tắc tuyệt đối.
Khi bạn xây dựng URL theo chương trình và chúng di chuyển giữa trình duyệt và chương trình phụ trợ, hãy chọn một tiêu chuẩn và tuân theo tiêu chuẩn đó. Sử dụng URL API của trình duyệt cho WHATWG. Nếu thư viện phụ trợ của bạn chặt chẽ hơn thì đó không phải là mâu thuẫn mà là sự lựa chọn về thiết kế.
Điều này không bao gồm những gì — phân tích cú pháp tên máy chủ, ký tự IPv6 và xử lý IDNA
Phân tích cú pháp tên máy chủ bao gồm các quy tắc IDNA, punycode và công ty đăng ký vượt ra ngoài phạm vi URL phân tích cú pháp hoàn toàn. Địa chỉ IPv6, các lược đồ đặc biệt như mailto: hoặc data: và các thành phần trống là các chủ đề riêng biệt hoàn toàn khác với mã hóa phần trăm. Giới hạn độ dài tên miền và tính hợp lệ của tên máy chủ khác nhau tùy theo nhà đăng ký và không liên quan đến cuộc thảo luận này. Cũng bị loại trừ: các tham chiếu tương đối và các quy tắc phân tích cú pháp theo sơ đồ cụ thể. Bài đăng này chỉ tập trung vào sự khác biệt về mã hóa và phân tích cú pháp.
Cuộc thảo luận này tập trung vào sự khác biệt về mã hóa và phân tích cú pháp để phân biệt các tiêu chuẩn này. Việc loại trừ các quy tắc tên máy chủ, quy tắc DNS và hành vi dành riêng cho lược đồ sẽ ngăn ngừa sự nhầm lẫn về quy tắc mã hóa phần trăm.
Bài học rút ra: URL giống nhau là hợp lệ ở một thế giới và có lỗi ở một thế giới khác — cách bộ mã hóa và giải mã URL cung cấp cho bạn mã hóa RFC 3986 đơn giản để bạn có thể xem những gì trình duyệt đã chuẩn hóa
Chuỗi URL giống nhau có thể hợp lệ theo một tiêu chuẩn và không hợp lệ theo tiêu chuẩn kia. Cả hai đều đúng trong mục tiêu thiết kế của riêng họ. Khi mã hóa các thành phần URL theo chương trình, hãy sử dụng công cụ phù hợp với môi trường của bạn. WHATWG mô tả những gì trình duyệt thực sự làm; RFC 3986 xác định ngữ pháp chính thức. Bộ mã hóa và giải mã URL hiển thị các quy tắc RFC 3986 cùng với hoạt động của trình duyệt để bạn có thể thấy sự khác biệt chính xác và chọn quy tắc phù hợp với trường hợp của mình.
Sự cố xuất hiện thường xuyên nhất khi URL vượt qua ranh giới từ trình duyệt đến chương trình phụ trợ. Hiểu được sự khác biệt này có nghĩa là xử lý việc vượt biển đó một cách có chủ ý chứ không phải vô tình hay nhầm lẫn.