Công cụ dành cho nhà phát triển · Bộ mã hóa và giải mã URL
Cộng với %20: lịch sử của ứng dụng/x-www-form-urlencoded
· Lý lịch
url-encoding html-forms http-standards
Biểu mẫu mã hóa khoảng trắng dưới dạng + trong khi tiêu chuẩn URI cho biết %20 và lý do là mang tính lịch sử. Bài đăng này theo dõi quy ước từ các biểu mẫu HTML ban đầu cho đến định nghĩa WHATWG ngày nay và giải thích lý do tại sao quy ước đó không bao giờ biến mất.
Cộng với %20—tại sao biểu mẫu và URI mã hóa khoảng trắng khác nhau
HTML biểu mẫu được gửi dưới dạng GET mã hóa dấu cách dưới dạng dấu cộng trong chuỗi truy vấn. Không gian tương tự sẽ trở thành %20 trong các URL theo sau RFC 3986. Cả hai đều đúng vì chúng tuân theo các tiêu chuẩn khác nhau. Các trường biểu mẫu chứa dấu cách trở thành tên=value+with+dấu cách trong mã hóa biểu mẫu nhưng %20 trong RFC 3986. Dấu phân biệt cộng phần trăm hai mươi đánh dấu tiêu chuẩn áp dụng cho dữ liệu của bạn.
Mã hóa biểu mẫu sử dụng dấu cộng cho dấu cách làm quy ước lịch sử từ định nghĩa gửi biểu mẫu ban đầu của RFC 1866 (1995), HTML 2.0. GET yêu cầu khoảng trắng được mã hóa dưới dạng dấu cộng, đặt dấu cộng cho chữ + được mã hóa dưới dạng %2B. Quy tắc này chỉ áp dụng cho ứng dụng/x-www-form-urlencoded, chứ không áp dụng cho cú pháp URI chung. Hàng tỷ khung máy chủ đã trở nên phụ thuộc vào quy ước này. Thử nghiệm cả hai đều cho thấy sự khác biệt rõ ràng: chế độ biểu mẫu tạo ra dấu cộng; Chế độ URI tạo ra %20. Bộ mã hóa và giải mã URL cung cấp cả hai chế độ để so sánh trực tiếp.
HTML biểu mẫu ban đầu và gửi GET — cách xác định mã hóa biểu mẫu và lý do + được chọn
RFC 1866 (1995) gửi biểu mẫu được xác định trong đó dấu cách trở thành dấu cộng và dấu cộng bằng chữ trở thành %2B. Điều này chỉ áp dụng cho ứng dụng/x-www-form-urlencoded. RFC 3986 đã chỉ định %20 cho cú pháp chung URI. Hai tiêu chuẩn cùng tồn tại một cách có chủ ý.
RFC 2396 đã làm rõ các bộ ký tự một cách chặt chẽ hơn các tiêu chuẩn trước đó. Nó chính thức hóa các ký tự dành riêng phục vụ cấu trúc URI so với các ký tự không được đặt trước dưới dạng dữ liệu bằng chữ. Các cơ quan tiêu chuẩn mã hóa hành vi của trình duyệt và proxy khi nó phát triển. RFC 3986 xuất hiện sau mà không thay đổi hành vi mã hóa, chỉ làm rõ ký hiệu. Tất cả các trình duyệt hiện tại đều chuẩn hóa mã hóa UTF-8. HTML biểu mẫu thông qua nút gửi gửi đơn đăng ký ở định dạng/x-www-form-urlencoded có dấu cộng cho khoảng trắng. Cấu trúc URI thủ công sử dụng %20. Hiểu cả hai tiêu chuẩn sẽ ngăn ngừa những bất ngờ khi tích hợp.
Thông số kỹ thuật RFC 1866 trở lên HTML — nơi quy tắc được viết ra và cách quy tắc đó khác với cú pháp URI
WHATWG URL Tiêu chuẩn chỉ định URLSearchParams.toString() tạo ra đầu ra ứng dụng/x-www-form-urlencoded với dấu cộng cho dấu cách. URL mã hóa phần trăm hàm tạo theo sau RFC 3986. Trình duyệt đang điều hướng đến URL với mã hóa dấu cách %20; biểu mẫu được gửi dưới dạng GET mã hóa dấu cộng. Những công cụ cơ bản khác nhau này phục vụ các mục đích khác nhau. EncodeURIComponent thủ công cung cấp %20 cho kiểu khoảng trắng—RFC 3986. Các biểu mẫu được gửi tới cùng URL sẽ gửi thêm. Máy chủ phân tích cú pháp gửi biểu mẫu mong đợi dấu cộng; việc nhận %20 gây ra lỗi tham số im lặng.
Việc kiểm tra cả hai đều cho thấy các giả định phía máy chủ mà bạn phụ thuộc vào. JavaScript URLSearchParams cung cấp khả năng ẩn mã hóa kiểu biểu mẫu an toàn cộng với độ phức tạp. Xây dựng URLSearchParams, nối thêm các mục nhập, gọi toString() để nhận ứng dụng/x-www-form-urlencoded với dấu cộng thích hợp. Hoặc xây dựng chuỗi truy vấn bằng EncodeURIComponent; bạn nhận được RFC 3986 %20. Không bao giờ trộn lẫn các phương pháp tiếp cận. Các chuỗi truy vấn có dấu cộng thủ công và mã hóaURIComponent tạo ra sự mơ hồ. Người nhận không thể phân biệt được dấu cộng có nghĩa là dấu cách hay dấu cộng theo nghĩa đen. Phương pháp tiếp cận tiêu chuẩn xử lý nhất quán.
Tiêu chuẩn URL ngày nay — ứng dụng/x-www-form-urlencoded dưới dạng một trình tuần tự hóa riêng biệt với các quy tắc riêng
JSON API thường từ chối dấu cộng dưới dạng khoảng trắng, mong đợi %20 cho mỗi RFC 3986. Khách hàng gửi cộng bị lỗi âm thầm: các tham số biến mất. Việc kiểm tra API bằng cả hai mã hóa sẽ cho biết chúng chấp nhận tiêu chuẩn nào. URLSearchParams trong JavaScript xử lý mã hóa biểu mẫu. Bộ mã hóa và giải mã URL tạo ra RFC 3986 %20.
HTML việc gửi biểu mẫu sẽ tự động xử lý việc mã hóa. Khung máy chủ của bạn quyết định áp dụng quy tắc nào. Rails, Django, PHP đều tự động coi dấu cộng là khoảng trắng trong dữ liệu biểu mẫu đã nhận. Nhưng việc xây dựng các chuỗi truy vấn theo cách thủ công cho cùng một điểm cuối lại vô cùng quan trọng. Một điểm cộng được tải lên tạo ra sự mơ hồ. Việc tuân thủ thông số kỹ thuật và hành vi của máy chủ trong thế giới thực có chút khác biệt. Ghi lại tiêu chuẩn mà điểm cuối của bạn mong đợi. Kiểm tra cả hai kiểu mã hóa. Mã phòng thủ xử lý cả hai một cách duyên dáng.
Ví dụ đã hoạt động: trường biểu mẫu tương tự được xem dưới dạng chuỗi truy vấn và nội dung yêu cầu - với + ở một nơi và %20 ở một nơi khác
JavaScript URLSearchParams áp dụng mã hóa biểu mẫu: dấu cách trở thành dấu cộng chứ không phải %20. URLSearchParams mới({q: "hello world"}) tạo ra "q=hello+world", không phải "q=hello%20world". Đây là quy tắc lịch sử của ứng dụng/x-www-form-urlencoded được tích hợp cụ thể vào JavaScript. Nhưng việc chuyển chuỗi này dưới dạng truy vấn thô sang URL mới vẫn giữ nguyên dấu cộng; chỉ URLSearchParams giải mã nó dưới dạng khoảng trắng. Trình xây dựng trung thành với những gì nó nhìn thấy. Sự khác biệt dấu cộng gây ra các lỗi thường gặp khi trộn các hàm không chính xác.
Hàm tạo URL và mã hóaURIComponent là các công cụ khác nhau. EncodeURIComponent mã hóa hầu hết mọi thứ ngoại trừ các chữ cái, chữ số và - _ . ! ~ * ' ( ). Nó giả định không có bối cảnh. Hàm tạo URL phân tích cú pháp URL thực tế và áp dụng quy tắc WHATWG cho mỗi thành phần. EncodeURIComponent biến "hello/world" thành "hello%2Fworld"; URL mới xem dấu gạch chéo là dấu phân cách đường dẫn. Đầu vào giống nhau, đầu ra khác nhau. Sử dụng EncodeURIComponent khi xây dựng URL bằng cách ghép các phần. Sử dụng hàm tạo URLSearchParams hoặc URL cho URL hoàn chỉnh hoặc một phần.
Tại sao không thể sửa được — hàng thập kỷ máy chủ và máy khách phụ thuộc vào hành vi hiện tại
Quy tắc mã hóa phần trăm được phát triển từ RFC 1738 (1994) đến RFC 2396 (1998) đến RFC 3986 (2005). Mỗi thế hệ đều làm sáng tỏ những điều mơ hồ. RFC 1738 tỏ ra thận trọng, coi các ký tự không an toàn vì web ban đầu có hỗ trợ ký tự hạn chế. Việc triển khai được chuẩn hóa trên UTF-8, việc triển khai trở nên nhất quán. Các tiêu chuẩn sau này đã nới lỏng các hạn chế đối với các ký tự được chứng minh là an toàn trên các hệ thống. Sự đồng thuận hiện đại: UTF-8 ở mọi nơi. Cơ quan tiêu chuẩn duy trì khả năng tương thích ngược một cách quyết liệt. Việc khắc phục sẽ cần đến sự phối hợp trên toàn thế giới – điều không thể thực hiện được sau ba thập kỷ. Hai tiêu chuẩn cùng tồn tại một cách có chủ ý.
Việc kiểm tra bằng cả dấu cộng và %20 sẽ tiết lộ các giả định của máy chủ. Nhật ký máy chủ hiển thị những gì khách hàng gửi. Các hình thức sử dụng dấu cộng; URL thủ công sử dụng %20. Chọn theo ngữ cảnh và làm theo tài liệu API.
Điều này không bao gồm những gì — phần thân nhiều phần/form-data và JSON
Việc kiểm tra cả hai mã hóa sẽ phát hiện hành vi của máy chủ. Gửi a+b theo cả hai cách. Nhiều máy chủ sản xuất mong đợi mã hóa biểu mẫu; API mới hơn yêu cầu %20. Sự lựa chọn của bạn phụ thuộc vào mong đợi của người nhận. URLSearchParams xử lý mã hóa biểu mẫu; EncodeURIComponent xử lý mã hóa RFC.
Không bao giờ kết hợp các phương pháp mã hóa. Giá trị được mã hóa bằng EncodeURIComponent %2B sau đó được chuyển tới URLSearchParams được mã hóa kép thành %252B. Giải mã một lần mang lại% 2B thay vì dấu cộng. Ký tự trở thành chuỗi phần trăm hai sáu thay vì dấu cộng. Kiểm tra các bước trung gian trong quá trình xây dựng của bạn. Mã hóa chỉ xảy ra chính xác một lần cho mỗi giá trị. Tài liệu về tiêu chuẩn mã hóa mà quy trình của bạn sử dụng. Kiểm tra với các ký tự đặc biệt bao gồm dấu cộng, dấu cách, ký hiệu.
Bài học rút ra: hai tiêu chuẩn, cả hai đều đúng trong ngữ cảnh — cách bộ mã hóa và giải mã URL cung cấp cho bạn biểu mẫu RFC 3986, với %20 cho khoảng trắng, để bạn biết mình đang xem cái nào
Việc phân chia cộng và hai mươi không phải là một lỗi cần khắc phục. Đó là tạo tác lịch sử của các tiêu chuẩn giải quyết các vấn đề riêng biệt một cách khác nhau. Việc sửa chữa sẽ đòi hỏi sự phối hợp trên toàn thế giới - không thể thực hiện được sau ba mươi năm. Các cơ quan tiêu chuẩn không phá vỡ web một cách hồi tố. RFC 3986, quy tắc biểu mẫu, cấu trúc URL của trình duyệt đều có tiêu chuẩn và lý do. RFC 1866 mã hóa biểu mẫu và mã hóa RFC 3986 URI phục vụ các lớp khác nhau. Mã hóa có chủ ý biết tiêu chuẩn của bạn. Kiểm tra tải trọng thực tế.
Chọn mã hóa theo ngữ cảnh. Biểu mẫu sử dụng điểm cộng theo tiêu chuẩn HTML. URI thủ công sử dụng %20 cho mỗi RFC 3986. API chỉ định những gì mong đợi; làm theo tài liệu hoặc kiểm tra cả hai. Bộ mã hóa và giải mã URL hiển thị RFC 3986. Cần mã hóa biểu mẫu? URLSearchParams thực hiện điều đó. Công cụ không trộn lẫn các bảng mã; sự hiểu biết các tiêu chuẩn ngăn chặn những điều bất ngờ. Mã hóa không nhất quán giữa các lớp gây ra mất tham số, cắt bớt, hỏng dữ liệu. Cả hai tiêu chuẩn đều đúng trong miền của chúng. Áp dụng có chủ ý và ghi lại.