Sử dụng Java, tôi muốn loại bỏ định danh đoạn và thực hiện một số chuẩn hóa đơn giản (ví dụ: lược đồ chữ thường, máy chủ) của một tập hợp URI đa dạng. URI đầu vào và đầu ra phải tương đương với một nghĩa HTTP chung.Chuẩn hóa các chuỗi URI được mã hóa trong Java
Thông thường, điều này phải đơn giản. Tuy nhiên, đối với các URI như http://blah.org/A_%28Secret%29.xml#blah
, phần trăm mã hóa (Secret)
, hành vi của java.util.URI
làm cho cuộc sống trở nên khó khăn.
Phương pháp chuẩn hóa phải trả lại http://blah.org/A_%28Secret%29.xml
vì các URI http://blah.org/A_%28Secret%29.xml
và http://blah.org/A_(Secret).xml
không tương đương với cách diễn giải [§2.2; RFC3968]
Vì vậy, chúng ta có hai phương pháp bình thường như sau:
URI u = new URI("http://blah.org/A_%28Secret%29.xml#blah");
System.out.println(u);
// prints "http://blah.org/A_%28Secret%29.xml#blah"
String path1 = u.getPath(); //gives "A_(Secret).xml"
String path2 = u.getRawPath(); //gives "A_%28Secret%29.xml"
//NORMALISE METHOD 1
URI norm1 = new URI(u.getScheme().toLowerCase(), u.getUserInfo(),
u.getHost().toLowerCase(), u.getPort(), path1,
u.getQuery(), null);
System.out.println(norm1);
// prints "http://blah.org/A_(Secret).xml"
//NORMALISE METHOD 2
URI norm2 = new URI(u.getScheme().toLowerCase(), u.getUserInfo(),
u.getHost().toLowerCase(), u.getPort(), path2,
u.getQuery(), null);
System.out.println(norm2);
// prints "http://blah.org/A_%2528Secret%2529.xml"
Như chúng ta thấy, các URI được phân tích và xây dựng lại mà không có sự nhận dạng mảnh.
Tuy nhiên, đối với phương pháp 1, u.getPath()
trả về URI chưa mã hóa, thay đổi URI cuối cùng.
Đối với phương pháp 2, u.getRawPath()
trả lại đường dẫn ban đầu, nhưng khi được chuyển đến hàm tạo URI
, Java quyết định thêm mã hóa kép.
Điều này giống như bẫy ngón tay của người Trung Quốc.
câu hỏi Vì vậy, hai chính:
- Tại sao
java.util.URI
cảm thấy cần phải chơi với mã hóa? - Phương pháp chuẩn hóa này có thể được triển khai như thế nào mà không gặp khó khăn với mã hóa phần trăm ban đầu?
(Tôi thà không cần phải thực hiện các phương pháp phân tích cú pháp/concatenate của java.util.URI
, đó là không tầm thường.)
EDIT: Dưới đây là một số thông tin thêm từ URI
javadoc.
Các đơn lập luận constructor đòi hỏi bất kỳ ký tự bất hợp pháp trong đối số của nó phải được trích dẫn và bảo bất kỳ octet và các nhân vật khác mà có mặt đã trốn thoát.
Các nhà thầu đa đối số đa đối số trích dẫn các ký tự không hợp lệ theo yêu cầu của các thành phần mà chúng xuất hiện. Ký tự phần trăm ('%') luôn được trích dẫn bởi các nhà xây dựng này. Bất kỳ ký tự nào khác được giữ nguyên.
Các getRawUserInfo, getRawPath, getRawQuery, getRawFragment, getRawAuthority, và getRawSchemeSpecificPart phương pháp trả lại giá trị của các thành phần tương ứng của chúng ở dạng thô, mà không giải thích bất kỳ octet trốn thoát. Các chuỗi được trả về bởi các phương thức này có thể chứa cả hai octet thoát và các ký tự khác, và sẽ không chứa bất kỳ ký tự không hợp lệ nào.
Các getUserInfo, getPath, getQuery, getFragment, getAuthority, và getSchemeSpecificPart phương pháp giải mã bất kỳ thoát octet trong các thành phần tương ứng của họ. Các chuỗi được trả về bởi các phương thức này có thể chứa cả các ký tự khác và các ký tự không hợp lệ, và sẽ không chứa bất kỳ octet thoát nào.
Phương thức toString trả về chuỗi URI với tất cả các báo giá cần thiết nhưng có thể chứa các ký tự khác.
Phương thức toASCIIString trả về chuỗi URI được trích dẫn đầy đủ và được mã hóa không chứa bất kỳ ký tự nào khác.
Vì vậy, tôi không thể sử dụng hàm tạo đa đối số mà không bị mã hóa URL sai lệch nội bộ theo lớp URI
. Pah!
Trường hợp sử dụng là trình thu thập thông tin. Chúng tôi muốn lấy một tập hợp các URI được trích xuất và "chuẩn hóa" chúng thành một tập hợp nhỏ nhất có thể, vẫn đảm bảo rằng nội dung đã truy xuất được đảm bảo giống nhau.(Câu hỏi http://stackoverflow.com/questions/2993649/how-to-normalize-a-url-in-java có liên quan nhưng không giải quyết vấn đề tước ID phân mảnh, với việc thay đổi mã hóa URL.) – badroit
Tôi cách xa các công cụ URI, và không chắc liệu bạn có cần nó theo cách tiêu chuẩn với API URI hay không, nhưng nếu tôi chỉ muốn có được chức năng này bằng cách nào đó, tôi sẽ 1) Lấy chuỗi con của url gốc cho đến khi sự xuất hiện đầu tiên của '#' hoặc '?' hoặc '&' vì đó là những gì thực sự tách url khỏi thông tin bổ sung hoặc 2) Cho phép URI tạo uri bình thường (ví dụ norm2) và sau đó thay thế tất cả% bằng bản gốc của một người trong chuỗi vị trí (1 của norm2 với 1 của bản gốc vv). Ofcourse này chỉ là nếu cách tiêu chuẩn là không thể sử dụng. –