Những ký tự nào tạo một URL không hợp lệ?
Đây có phải là các URL hợp lệ không?
example.com/file[/].html
http://example.com/file[/].html
Những ký tự nào tạo một URL không hợp lệ?
Đây có phải là các URL hợp lệ không?
example.com/file[/].html
http://example.com/file[/].html
Câu trả lời:
Trong các URI chung như được định nghĩa bởi RFC 3986 (xem Phần 2: Ký tự ) có thể chứa bất kỳ 84 ký tự nào sau đây:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=
Lưu ý rằng danh sách này không nêu rõ trong URI những ký tự này có thể xảy ra.
Bất kỳ ký tự nào khác cần được mã hóa bằng mã hóa phần trăm ( %
hh
). Mỗi phần của URI có những hạn chế hơn nữa về những ký tự cần được thể hiện bằng một từ được mã hóa theo phần trăm.
/^([!#$&-;=?-[]_a-z~]|%[0-9a-fA-F]{2})+$/
Có điều gì khác mà bạn thấy nó nên chấp nhận không? (Nói rõ hơn, regex đó chỉ kiểm tra xem chuỗi có chứa các ký tự URL hợp lệ chứ không phải nếu chuỗi chứa URL được tạo tốt.)
Để thêm một số làm rõ và trực tiếp giải quyết câu hỏi ở trên, có một số loại ký tự gây ra sự cố cho URL và URI.
Có một số ký tự không được phép và không bao giờ xuất hiện trong URL / URI, các ký tự dành riêng (được mô tả bên dưới) và các ký tự khác có thể gây ra sự cố trong một số trường hợp, nhưng được đánh dấu là "không an toàn" hoặc "không an toàn". Giải thích tại sao các ký tự bị hạn chế được viết rõ ràng trong RFC-1738 (URL) và RFC-2396 (URI). Lưu ý RFC-3986 mới hơn (cập nhật lên RFC-1738) xác định cấu trúc của các ký tự được phép trong ngữ cảnh cụ thể nhưng thông số cũ hơn cung cấp mô tả đơn giản và tổng quát hơn về các ký tự không được phép theo các quy tắc sau.
Các ký tự US-ASCII bị loại trừ không được phép trong cú pháp URI:
control = <US-ASCII coded characters 00-1F and 7F hexadecimal>
space = <US-ASCII coded character 20 hexadecimal>
delims = "<" | ">" | "#" | "%" | <">
Ký tự "#" được loại trừ vì nó được sử dụng để phân định URI khỏi mã định danh phân đoạn. Phần trăm ký tự "%" được loại trừ vì nó được sử dụng để mã hóa các ký tự thoát. Nói cách khác, "#" và "%" là các ký tự dành riêng phải được sử dụng trong ngữ cảnh cụ thể.
Danh sách các ký tự không được phép được cho phép nhưng có thể gây ra sự cố:
unwise = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "`"
Các ký tự được bảo lưu trong thành phần truy vấn và / hoặc có ý nghĩa đặc biệt trong URI / URL:
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
Lớp cú pháp "dành riêng" ở trên đề cập đến các ký tự được phép trong URI, nhưng có thể không được phép trong một thành phần cụ thể của cú pháp URI chung. Các ký tự trong bộ "dành riêng" không được bảo lưu trong tất cả các ngữ cảnh . Ví dụ, tên máy chủ có thể chứa tên người dùng tùy chọn để nó có thể giống như ftp://user@hostname/
ký tự '@' có ý nghĩa đặc biệt.
Dưới đây là ví dụ về một URL có các ký tự không hợp lệ và không chính xác (ví dụ: '$', '[', ']') và phải được mã hóa chính xác:
http://mw1.google.com/mw-earth-vectordb/kml-samples/gp/seattle/gigapxl/$[level]/r$[y]_c$[x].jpg
Một số hạn chế ký tự cho URI / URL phụ thuộc vào ngôn ngữ lập trình. Ví dụ: '|' Ký tự (0x7C) mặc dù chỉ được đánh dấu là "không khôn ngoan" trong thông số URI sẽ ném URISyntaxException trong hàm tạo Java java.net.URI để URL như http://api.google.com/q?exp=a|b
không được phép và phải được mã hóa thay vì http://api.google.com/q?exp=a%7Cb
sử dụng Java với một đối tượng URI.
?
chỉ tốt trong phần truy vấn, nhưng không thể trước phần đó và tôi không nghĩ @
thuộc về bất kỳ danh sách nào trong số này. Ồ, và thay vì %25
trong chuỗi cuối cùng, ý bạn là %7C
sao?
Hầu hết các câu trả lời hiện có ở đây là không thực tế vì chúng hoàn toàn bỏ qua việc sử dụng các địa chỉ trong thế giới thực như:
Đầu tiên, một sự lạc đề vào thuật ngữ. Những địa chỉ này là gì? Chúng có phải là URL hợp lệ không?
Trong lịch sử, câu trả lời là "không". Theo RFC 3986 , từ năm 2005, các địa chỉ đó không phải là URI (và do đó không phải là URL, vì URL là một loại URI ). Theo thuật ngữ của các tiêu chuẩn IETF năm 2005, chúng ta nên gọi chúng là IRI (Mã định danh tài nguyên quốc tế hóa), như được định nghĩa trong RFC 3987 , về mặt kỹ thuật không phải là URI nhưng có thể được chuyển đổi thành URI đơn giản bằng cách mã hóa phần trăm tất cả các ký tự không phải ASCII trong IRI .
Theo thông số kỹ thuật hiện đại, câu trả lời là "có". Các mức sống WHATWG chỉ đơn giản là phân loại tất cả mọi thứ mà trước đây sẽ được gọi là "URI" hoặc "IRI" là "URL". Điều này phù hợp với thuật ngữ được chỉ định với cách những người bình thường không đọc thông số sử dụng từ "URL", đó là một trong những mục tiêu của thông số kỹ thuật .
Theo ý nghĩa mới hơn của "URL" này, những ký tự nào được phép? Trong nhiều phần của URL, chẳng hạn như chuỗi và đường dẫn truy vấn, chúng tôi được phép sử dụng các "đơn vị URL" tùy ý , đó là
"Điểm mã URL" là gì?
Các điểm mã URL là ASCII chữ và số, U + 0021 (!), U + 0024 ($), U + 0026 (&), U + 0027 ('), U + 0028 PARENTHESIS, U + 0029 PARENTHESIS, U + 0029 002A (*), U + 002B (+), U + 002C (,), U + 002D (-), U + 002E (.), U + 002F (/), U + 003A (:), U + 003B (;), U + 003D (=), U + 003F (?), U + 0040 (@), U + 005F (_), U + 007E (~) và các điểm mã trong phạm vi U + 00A0 đến U + 10FFFD, bao gồm, không bao gồm đại diện thay thế và không ký tự.
(Lưu ý rằng danh sách "điểm mã URL" không bao gồm %
, nhưng điều đó %
được cho phép trong "đơn vị mã URL" nếu chúng là một phần của chuỗi mã hóa phần trăm.)
Nơi duy nhất tôi có thể phát hiện ra nơi thông số kỹ thuật cho phép sử dụng bất kỳ ký tự nào không có trong bộ này là trong máy chủ lưu trữ , nơi các địa chỉ IPv6 được đặt trong [
và các ]
ký tự. Ở mọi nơi khác trong URL, các đơn vị URL được cho phép hoặc một số bộ ký tự thậm chí còn hạn chế hơn.
Vì lợi ích của lịch sử và vì nó không được khám phá đầy đủ ở những nơi khác trong các câu trả lời ở đây, chúng ta hãy kiểm tra được cho phép theo cặp thông số kỹ thuật cũ hơn.
Trước hết, chúng tôi có hai loại ký tự dành riêng RFC 3986 :
:/?#[]@
, là một phần của cú pháp chung cho URI được xác định trong RFC 3986!$&'()*+,;=
, không phải là một phần của cú pháp chung của RFC, nhưng được dành riêng để sử dụng làm thành phần cú pháp của các lược đồ URI cụ thể. Ví dụ, dấu chấm phẩy và dấu phẩy được sử dụng như một phần của cú pháp của URI dữ liệu , và &
và =
được sử dụng như một phần của phổ biến ?foo=bar&qux=baz
định dạng trong chuỗi truy vấn (mà không được quy định bởi RFC 3986).Bất kỳ ký tự dành riêng nào ở trên đều có thể được sử dụng hợp pháp trong URI mà không cần mã hóa, để phục vụ mục đích cú pháp của chúng hoặc chỉ là ký tự chữ trong dữ liệu ở một số nơi mà việc sử dụng đó không thể bị hiểu sai là ký tự phục vụ mục đích cú pháp của nó. (Ví dụ: mặc dù /
có ý nghĩa cú pháp trong một URL, bạn có thể sử dụng nó không được mã hóa trong chuỗi truy vấn, vì nó không có nghĩa trong chuỗi truy vấn.)
RFC 3986 cũng chỉ định một số ký tự không được giám sát , luôn có thể được sử dụng đơn giản để thể hiện dữ liệu mà không cần mã hóa:
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~
Cuối cùng, %
bản thân nhân vật được phép mã hóa phần trăm.
Chỉ để lại các ký tự ASCII sau bị cấm xuất hiện trong URL:
"<>\^`{|}
Mọi ký tự khác từ ASCII đều có thể xuất hiện hợp pháp trong một URL.
Sau đó, RFC 3987 mở rộng tập hợp các ký tự không được giám sát với các phạm vi ký tự unicode sau:
%xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF
/ %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD
/ %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD
/ %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD
/ %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD
/ %xD0000-DFFFD / %xE1000-EFFFD
Các lựa chọn khối này từ thông số kỹ thuật cũ có vẻ kỳ quái và tùy tiện đưa ra các định nghĩa khối Unicode mới nhất ; điều này có lẽ là do các khối đã được thêm vào trong thập kỷ kể từ khi RFC 3987 được viết.
Cuối cùng, có lẽ đáng lưu ý rằng chỉ cần biết các ký tự nào có thể xuất hiện hợp pháp trong URL là không đủ để nhận ra một số chuỗi đã cho có phải là URL hợp pháp hay không, vì một số ký tự chỉ hợp pháp trong các phần cụ thể của URL. Ví dụ: các ký tự dành riêng [
và ]
hợp pháp là một phần của máy chủ lưu trữ bằng chữ IPv6 trong một URL như http: // [1080 :: 8: 800: 200C: 417A] / foo nhưng không hợp pháp trong bất kỳ ngữ cảnh nào khác, vì vậy, Ví dụ của OP http://example.com/file[/].html
là bất hợp pháp.
Trong câu hỏi bổ sung của bạn, bạn đã hỏi nếu www.example.com/file[/].html
một URL hợp lệ.
URL đó không hợp lệ vì URL là một loại URI và URI hợp lệ phải có sơ đồ như http:
(xem RFC 3986 ).
Nếu bạn muốn hỏi nếu http://www.example.com/file[/].html
một URL hợp lệ thì câu trả lời vẫn là không vì các ký tự dấu ngoặc vuông không hợp lệ ở đó.
Các ký tự dấu ngoặc vuông được dành riêng cho các URL ở định dạng này: http://[2001:db8:85a3::8a2e:370:7334]/foo/bar
(nghĩa là một chữ IPv6 thay vì tên máy chủ)
Thật đáng để đọc RFC 3986 một cách cẩn thận nếu bạn muốn hiểu vấn đề đầy đủ.
[
và ]
không URI hợp lệ trong gần parsers tôi đã thấy. Điều này thực sự đã làm tôi khó chịu trong thế giới thực: stackoverflow.com/questions/11038967/iêu
Unwise
rất nghiêm túc đối với các URI và vẫn ổn với các thư viện URL. Đó là không có cờ để bỏ qua Unwise
. Tôi sẽ phải kiểm tra Rust lang (vì nó đang được xây dựng cho trình duyệt. Tôi tò mò không biết nó làm gì) cho các URL. Hầu hết các trình duyệt mặc dù cũng sẽ vui vẻ vượt qua "[", "]". Vì vậy, trong lý thuyết giống như tôi đã nói với C / C ++, chúng là sub / super nhưng thực tế không phải vậy. Nó phụ thuộc rất nhiều vào việc giải thích thông số kỹ thuật và ngữ nghĩa của siêu / tập hợp con.
Tất cả các ký tự hợp lệ có thể được sử dụng trong URI ( URL là một loại URI ) được xác định trong RFC 3986 .
Tất cả các ký tự khác có thể được sử dụng trong một URL với điều kiện là chúng được "Mã hóa URL" trước tiên. Điều này liên quan đến việc thay đổi ký tự không hợp lệ cho các "mã" cụ thể (thường ở dạng ký hiệu phần trăm (%) theo sau là số thập lục phân).
Liên kết này, Tham chiếu mã hóa URL HTML , chứa danh sách các mã hóa cho các ký tự không hợp lệ.
Một số phạm vi ký tự Unicode là HTML5 hợp lệ , mặc dù có thể vẫn không nên sử dụng chúng.
Ví dụ: các href
tài liệu nói rằng http://www.w3.org/TR/html5/links.html#attr-hyperlink-href :
Thuộc tính href trên phần tử a và khu vực phải có giá trị là URL hợp lệ có khả năng được bao quanh bởi khoảng trắng.
Sau đó, định nghĩa của "URL hợp lệ" trỏ đến http://url.spec.whatwg.org/ , cho biết nó nhằm mục đích:
Căn chỉnh RFC 3986 và RFC 3987 với các triển khai hiện đại và lỗi thời trong quy trình.
Tài liệu đó xác định các điểm mã URL là:
Chữ cái ASCII, "!", "$", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/" , ":", ";", "=", "?", "@", "_", "~" và các điểm mã trong phạm vi U + 00A0 đến U + D7FF, U + E000 đến U + FDCF , U + FDF0 thành U + FFFD, U + 10000 đến U + 1FFFD, U + 20000 đến U + 2FFFD, U + 30000 đến U + 3FFFD, U + 40000 đến U + 4FFFD, U + 50000 đến U + 5FFFD, U +60000 đến U + 6FFFD, U + 70000 đến U + 7FFFD, U + 80000 đến U + 8FFFD, U + 90000 đến U + 9FFFD, U + A0000 đến U + AFFFD, U + B0000 đến U + BFFFD, U + B0000 đến U + CFFFD, U + D0000 đến U + DFFFD, U + E1000 sang U + EFFFD, U + F0000 sang U + FFFFD, U + 100000 đến U + 10FFFD.
Thuật ngữ "điểm mã URL" sau đó được sử dụng trong câu lệnh:
Nếu c không phải là điểm mã URL và không phải là "%", lỗi phân tích cú pháp.
trong một số phần của thuật toán phân tích cú pháp, bao gồm lược đồ, quyền hạn, đường dẫn tương đối, truy vấn và trạng thái phân đoạn: về cơ bản là toàn bộ URL.
Ngoài ra, trình xác thực http://validator.w3.org/ chuyển cho các URL như "你好"
và không chuyển cho các URL có các ký tự như khoảng trắng"a b"
Tất nhiên, như Stephen C đã đề cập, nó không chỉ là về các nhân vật mà còn về bối cảnh: bạn phải hiểu toàn bộ thuật toán. Nhưng vì lớp "điểm mã URL" được sử dụng trên các điểm chính của thuật toán, nên nó mang lại ý tưởng tốt về những gì bạn có thể sử dụng hay không.
Xem thêm: Ký tự Unicode trong URL
Tôi cần chọn ký tự để phân tách các chuỗi trong chuỗi, vì vậy tôi đã quyết định tự tạo danh sách các ký tự không thể tìm thấy trong URL:
>>> allowed = "-_.~!*'();:@&=+$,/?%#[]?@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
>>> from string import printable
>>> ''.join(set(printable).difference(set(allowed)))
'`" <\x0b\n\r\x0c\\\t{^}|>'
Vì vậy, các lựa chọn có thể là dòng mới, tab, dấu cách, dấu gạch chéo ngược và "<>{}^|
. Tôi đoán tôi sẽ đi với không gian hoặc dòng mới. :)
Không thực sự là một câu trả lời cho câu hỏi của bạn nhưng việc xác thực url là thực sự nghiêm trọng Bạn có thể tốt hơn hết là xác thực tên miền và để lại một phần truy vấn của url. Đó là kinh nghiệm của tôi. Bạn cũng có thể dùng đến việc ping url và xem liệu nó có dẫn đến phản hồi hợp lệ hay không nhưng điều đó có thể là quá nhiều cho một nhiệm vụ đơn giản như vậy.
Các biểu thức thông thường để phát hiện url rất phong phú, google nó :)
Tôi đang triển khai yêu cầu / người viết / phản hồi http (0.9, 1.0, 1.1) cũ. Yêu cầu URI là nơi có vấn đề nhất.
Bạn không thể chỉ sử dụng RFC 1738, 2396 hoặc 3986. Có nhiều máy khách và máy chủ HTTP cũ cho phép nhiều ký tự hơn. Vì vậy, tôi đã thực hiện nghiên cứu dựa trên nhật ký truy cập máy chủ web vô tình được công bố:"GET URI HTTP/1.0" 200
.
Tôi đã thấy rằng các ký tự không chuẩn sau đây thường được sử dụng trong URI:
\ { } < > | ` ^ "
Những ký tự này được mô tả trong RFC 1738 là không an toàn .
Nếu bạn muốn tương thích với tất cả các máy khách và máy chủ HTTP cũ - bạn phải cho phép các ký tự này trong URI yêu cầu.
Vui lòng đọc thêm thông tin về nghiên cứu này trong http-og .
Tôi đã đưa ra một vài biểu thức chính quy cho PHP sẽ chuyển đổi các url trong văn bản thành các thẻ neo. (Đầu tiên, nó chuyển đổi tất cả các url www thành http: // sau đó chuyển đổi tất cả các url bằng https ?: // thành a href = ... các liên kết html
$string = preg_replace('/(https?:\/\/)([!#$&-;=?\-\[\]_a-z~%]+)/sim', '<a href="$1$2">$2</a>',
preg_replace('/(\s)((www\.)([!#$&-;=?\-\[\]_a-z~%]+))/sim', '$1http://$2', $string)
);