Karakter mana yang membuat URL tidak valid?
Apakah ini URL yang valid?
example.com/file[/].html
http://example.com/file[/].html
Karakter mana yang membuat URL tidak valid?
Apakah ini URL yang valid?
example.com/file[/].html
http://example.com/file[/].html
Jawaban:
Secara umum URI seperti yang didefinisikan oleh RFC 3986 (lihat Bagian 2: Karakter ) dapat berisi salah satu dari 84 karakter berikut:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=
Perhatikan bahwa daftar ini tidak menyatakan di mana dalam URI karakter ini dapat terjadi.
Karakter lain apa pun harus dikodekan dengan persen-penyandian ( %
hh
). Setiap bagian dari URI memiliki batasan lebih lanjut tentang karakter apa yang perlu diwakili oleh kata yang dikodekan persen.
/^([!#$&-;=?-[]_a-z~]|%[0-9a-fA-F]{2})+$/
Apakah ada hal lain yang Anda temukan seharusnya sudah diterima? (Hanya untuk memperjelas, regex itu hanya memeriksa apakah string berisi karakter URL yang valid, bukan jika string tersebut berisi URL yang terbentuk dengan baik.)
Untuk menambahkan beberapa klarifikasi dan langsung menjawab pertanyaan di atas, ada beberapa kelas karakter yang menyebabkan masalah untuk URL dan URI.
Ada beberapa karakter yang dilarang dan tidak boleh muncul di URL / URI, karakter yang dipesan (dijelaskan di bawah), dan karakter lain yang dapat menyebabkan masalah dalam beberapa kasus, tetapi ditandai sebagai "tidak bijaksana" atau "tidak aman". Penjelasan mengapa karakter dibatasi jelas dijabarkan dalam RFC-1738 (URL) dan RFC-2396 (URI). Perhatikan bahwa RFC-3986 yang lebih baru (pembaruan ke RFC-1738) mendefinisikan konstruksi karakter apa yang diperbolehkan dalam konteks tertentu, tetapi spesifikasi yang lebih lama menawarkan deskripsi yang lebih sederhana dan lebih umum tentang karakter yang tidak diizinkan dengan aturan berikut.
Karakter US-ASCII yang dikecualikan yang tidak diizinkan dalam sintaksis URI:
control = <US-ASCII coded characters 00-1F and 7F hexadecimal>
space = <US-ASCII coded character 20 hexadecimal>
delims = "<" | ">" | "#" | "%" | <">
Karakter "#" dikecualikan karena digunakan untuk membatasi URI dari pengidentifikasi fragmen. Persentase karakter "%" dikecualikan karena digunakan untuk penyandian karakter yang diloloskan. Dengan kata lain, "#" dan "%" adalah karakter khusus yang harus digunakan dalam konteks tertentu.
Daftar karakter tidak bijaksana diperbolehkan tetapi dapat menyebabkan masalah:
unwise = "{" | "}" | "|" | "\" | "^" | "[" | "]" | "`"
Karakter yang dicadangkan dalam komponen permintaan dan / atau memiliki makna khusus dalam URI / URL:
reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
Kelas sintaks "dilindungi" di atas mengacu pada karakter-karakter yang diizinkan dalam URI, tetapi yang mungkin tidak diizinkan dalam komponen tertentu dari sintaksis URI generik. Karakter dalam set "dilindungi undang-undang" tidak dicadangkan di semua konteks . Nama host, misalnya, dapat berisi nama pengguna opsional sehingga bisa berupa sesuatu di ftp://user@hostname/
mana karakter '@' memiliki arti khusus.
Berikut adalah contoh URL yang memiliki karakter tidak valid dan tidak bijaksana (mis. '$', '[', ']') Dan harus dikodekan dengan benar:
http://mw1.google.com/mw-earth-vectordb/kml-samples/gp/seattle/gigapxl/$[level]/r$[y]_c$[x].jpg
Beberapa batasan karakter untuk URI / URL tergantung pada bahasa pemrograman. Misalnya, '|' (0x7C) karakter meskipun hanya ditandai sebagai "tidak bijaksana" dalam spesifikasi URI akan melempar URISyntaxException di konstruktor Java java.net.URI sehingga URL suka http://api.google.com/q?exp=a|b
tidak diperbolehkan dan harus dikodekan sebagai gantinya http://api.google.com/q?exp=a%7Cb
menggunakan Java dengan objek objek URI.
?
saja di bagian permintaan, tetapi tidak mungkin sebelumnya, dan saya pikir tidak @
termasuk dalam salah satu dari daftar ini. Oh, dan bukannya %25
di string terakhir, bukankah maksud Anda %7C
?
Sebagian besar jawaban yang ada di sini tidak praktis karena sama sekali mengabaikan penggunaan alamat dunia nyata seperti:
Pertama, penyimpangan ke dalam terminologi. Apa yang alamat ini? Apakah itu URL yang valid?
Secara historis, jawabannya adalah "tidak". Menurut RFC 3986 , sejak 2005, alamat tersebut bukan URI (dan karena itu bukan URL, karena URL adalah jenis URI ). Sesuai dengan terminologi standar IETF 2005, kita harus menyebutnya IRI (Internationalized Resource Identifiers), sebagaimana didefinisikan dalam RFC 3987 , yang secara teknis bukan URI tetapi dapat dikonversi ke URI hanya dengan persen-pengkodean semua karakter non-ASCII dalam IRI .
Per spec modern, jawabannya adalah "ya". The WHATWG Living Standard hanya mengklasifikasikan segala sesuatu yang sebelumnya disebut "URI" atau "IRI" sebagai "URL". Ini disejajarkan dengan specced terminologi dengan cara orang normal yang belum membaca spec penggunaan kata "URL", yang merupakan salah satu spec gol .
Per makna "URL" yang lebih baru ini, karakter apa yang diizinkan? Dalam banyak bagian dari URL, seperti string dan jalan, kita diperbolehkan untuk menggunakan sewenang-wenang "unit URL" , yang
Apa itu "poin kode URL"?
The poin kode URL yang ASCII alfanumerik, U + 0021 (!), U + 0024 ($), U + 0026 (&), U + 0027 ( '), U + 0028 KIRI kurung, U + 0029 KANAN kurung, U + 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 (~), dan titik kode dalam kisaran U + 00A0 ke U + 10FFFD, inklusif, tidak termasuk pengganti dan karakter bukan.
(Perhatikan bahwa daftar "titik kode URL" tidak termasuk %
, tetapi itu %
diizinkan di "unit kode URL" jika mereka bagian dari urutan penyandian persen.)
Satu-satunya tempat saya bisa melihat di mana spec memungkinkan penggunaan karakter apa pun yang tidak ada dalam set ini adalah di host , di mana alamat IPv6 tertutup [
dan ]
karakter. Di tempat lain di URL, unit URL diizinkan atau beberapa set karakter yang lebih ketat.
Demi sejarah, dan karena itu tidak dieksplorasi sepenuhnya di tempat lain dalam jawaban di sini, mari kita periksa diizinkan di bawah pasangan spesifikasi yang lebih tua.
Pertama-tama, kami memiliki dua jenis karakter khusus RFC 3986 :
:/?#[]@
, yang merupakan bagian dari sintaksis generik untuk URI yang ditentukan dalam RFC 3986!$&'()*+,;=
, yang bukan bagian dari sintaksis umum RFC, tetapi dicadangkan untuk digunakan sebagai komponen sintaksis dari skema URI tertentu. Misalnya, titik koma dan koma digunakan sebagai bagian dari sintaks URI data , dan &
dan =
digunakan sebagai bagian dari mana-mana ?foo=bar&qux=baz
format string query (yang tidak ditentukan oleh RFC 3986).Setiap karakter yang dilindungi di atas dapat digunakan secara legal dalam URI tanpa penyandian, baik untuk melayani tujuan sintaksisnya atau hanya sebagai karakter literal dalam data di beberapa tempat di mana penggunaan tersebut tidak dapat disalahartikan sebagai karakter yang melayani tujuan sintaksisnya. (Misalnya, meskipun /
memiliki makna sintaksis dalam URL, Anda dapat menggunakannya tanpa enkripsi dalam string kueri, karena itu tidak memiliki makna dalam string kueri.)
RFC 3986 juga menentukan beberapa karakter tanpa pagu harga , yang selalu dapat digunakan hanya untuk merepresentasikan data tanpa pengkodean apa pun:
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~
Akhirnya, %
karakter itu sendiri diperbolehkan untuk penyandian-persen.
Yang tersisa hanya karakter ASCII berikut yang dilarang muncul di URL:
"<>\^`{|}
Setiap karakter lain dari ASCII dapat secara hukum ditampilkan dalam URL.
Kemudian RFC 3987 memperluas rangkaian karakter yang tidak diawetkan dengan rentang karakter unicode berikut:
%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
Pilihan blok ini dari spec lama tampak aneh dan sewenang-wenang diberikan definisi blok Unicode terbaru ; ini mungkin karena blok telah ditambahkan pada dekade sejak RFC 3987 ditulis.
Terakhir, mungkin perlu dicatat bahwa mengetahui karakter mana saja yang dapat muncul secara legal di URL tidak cukup untuk mengenali apakah beberapa string yang diberikan adalah URL yang legal atau tidak, karena beberapa karakter hanya legal di bagian-bagian tertentu dari URL. Sebagai contoh, karakter yang dilindungi undang-undang [
dan ]
legal sebagai bagian dari host literal IPv6 dalam URL seperti http: // [1080 :: 8: 800: 200C: 417A] / foo tetapi tidak legal dalam konteks lain, jadi Contoh OP http://example.com/file[/].html
adalah ilegal.
Dalam pertanyaan tambahan, Anda bertanya apakah www.example.com/file[/].html
URL yang valid.
URL itu tidak valid karena URL adalah jenis URI dan URI yang valid harus memiliki skema seperti http:
(lihat RFC 3986 ).
Jika Anda bermaksud menanyakan apakah http://www.example.com/file[/].html
URL yang valid maka jawabannya masih tidak karena karakter kurung siku tidak valid di sana.
Karakter kurung siku dicadangkan untuk URL dalam format ini: http://[2001:db8:85a3::8a2e:370:7334]/foo/bar
(yaitu literal IPv6 alih-alih nama host)
Sebaiknya baca RFC 3986 dengan cermat jika Anda ingin memahami masalah ini sepenuhnya.
[
dan ]
tidak URI berlaku untuk hampir parser saya telah melihat. Ini sebenarnya telah mengacaukan saya di dunia nyata: stackoverflow.com/questions/11038967/...
Unwise
serius URI dan tidak masalah dengan pustaka URL. Itu tidak ada bendera untuk diabaikan Unwise
. Saya harus memeriksa apa yang dilakukan Rust lang (karena sedang dibangun untuk browser, saya ingin tahu apa fungsinya) untuk URL. Sebagian besar browser dengan senang hati akan meneruskan "[", "]" juga. Jadi secara teori seperti yang saya katakan dengan C / C ++ mereka sub / super tetapi kenyataannya tidak begitu benar. Ini sangat tergantung pada interpretasi spesifikasi dan semantik super / subset.
Semua karakter yang valid yang dapat digunakan dalam URI ( URL adalah jenis URI ) didefinisikan dalam RFC 3986 .
Semua karakter lain dapat digunakan dalam URL asalkan mereka "URL Dikodekan" terlebih dahulu. Ini melibatkan mengubah karakter yang tidak valid untuk "kode" tertentu (biasanya dalam bentuk simbol persen (%) diikuti oleh angka heksadesimal).
Tautan ini, Referensi Penyandian URL HTML , berisi daftar penyandian untuk karakter yang tidak valid.
Beberapa rentang karakter Unicode adalah HTML5 yang valid , meskipun mungkin masih bukan ide yang baik untuk menggunakannya.
Misalnya, href
dokumen mengatakan http://www.w3.org/TR/html5/links.html#attr-hyperlink-href :
Atribut href pada elemen dan area harus memiliki nilai yang merupakan URL valid yang berpotensi dikelilingi oleh spasi.
Kemudian definisi "URL yang valid" menunjuk ke http://url.spec.whatwg.org/ , yang mengatakan bertujuan untuk:
Sejajarkan RFC 3986 dan RFC 3987 dengan implementasi kontemporer dan usang dalam proses.
Dokumen itu mendefinisikan poin kode URL sebagai:
Alfanumerik ASCII, "!", "$", "&", "'", "(", ")", "*", "+", ",", "-", ",". "," / " , ":", ";", "=", "?", "@", "_", "~", dan titik kode dalam rentang U + 00A0 hingga U + D7FF, U + E000 hingga U + FDCF , U + FDF0 ke U + FFFD, U + 10000 ke U + 1FFFD, U + 20000 ke U + 2FFFD, U + 30000 ke U + 3FFFD, U + 40000 ke U + 4FFFD, U + 50000 ke U + 5FFFD, U +60000 ke U + 6FFFD, U + 70000 ke U + 7FFFD, U + 80000 ke U + 8FFFD, U + 90000 ke U + 9FFFD, U + A0000 ke U + AFFFD, U + B0000 ke U + BFFFD, U + C0000 ke U + CFFFD, U + D0000 ke U + DFFFD, U + E1000 ke U + EFFFD, U + F0000 ke U + FFFFD, U + 100000 ke U + 10FFFD.
Istilah "poin kode URL" kemudian digunakan dalam pernyataan:
Jika c bukan titik kode URL dan bukan "%", kesalahan parse.
di beberapa bagian algoritma penguraian, termasuk skema, otoritas, jalur relatif, kueri, dan status fragmen: jadi pada dasarnya seluruh URL.
Juga, validator http://validator.w3.org/ meneruskan untuk URL seperti "你好"
, dan tidak lulus untuk URL dengan karakter seperti spasi"a b"
Tentu saja, seperti yang disebutkan oleh Stephen C, ini bukan hanya tentang karakter tetapi juga tentang konteks: Anda harus memahami keseluruhan algoritma. Tetapi karena kelas "titik kode URL" digunakan pada titik-titik kunci dari algoritma, itu yang memberikan ide bagus tentang apa yang dapat Anda gunakan atau tidak.
Lihat juga: Karakter Unicode dalam URL
Saya perlu memilih karakter untuk memisahkan url dalam string, jadi saya memutuskan untuk membuat daftar karakter yang tidak dapat ditemukan di URL sendiri:
>>> allowed = "-_.~!*'();:@&=+$,/?%#[]?@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
>>> from string import printable
>>> ''.join(set(printable).difference(set(allowed)))
'`" <\x0b\n\r\x0c\\\t{^}|>'
Jadi, pilihan yang mungkin adalah baris baru, tab, spasi, garis miring terbalik dan "<>{}^|
. Saya kira saya akan pergi dengan ruang atau baris baru. :)
Bukan jawaban untuk pertanyaan Anda, tetapi memvalidasi url benar-benar pita yang serius. Anda mungkin lebih baik memvalidasi nama domain dan meninggalkan bagian permintaan dari url. Itulah pengalaman saya. Anda juga dapat menggunakan ping url dan melihat apakah itu menghasilkan respons yang valid tetapi itu mungkin terlalu banyak untuk tugas yang begitu sederhana.
Ekspresi reguler untuk mendeteksi url berlimpah, google it :)
Saya menerapkan permintaan dan respons pembaca / penulis http (0.9, 1.0, 1.1) yang lama. Meminta URI adalah tempat yang paling bermasalah.
Anda tidak bisa hanya menggunakan RFC 1738, 2396 atau 3986 apa adanya. Ada banyak klien dan server HTTP lama yang memungkinkan lebih banyak karakter. Jadi saya sudah membuat penelitian berdasarkan sengaja diterbitkan akses webserver log: "GET URI HTTP/1.0" 200
.
Saya menemukan bahwa karakter non-standar berikut sering digunakan di URI:
\ { } < > | ` ^ "
Karakter-karakter ini dijelaskan dalam RFC 1738 sebagai tidak aman .
Jika Anda ingin kompatibel dengan semua klien dan server HTTP lama - Anda harus mengizinkan karakter ini dalam URI permintaan.
Silakan baca informasi lebih lanjut tentang penelitian ini di http-og .
Saya datang dengan beberapa ekspresi reguler untuk PHP yang akan mengonversi url dalam teks menjadi tag jangkar. (Pertama itu mengonversi semua url www ke http: // lalu mengonversi semua url dengan https?: // ke href = ... tautan html
$string = preg_replace('/(https?:\/\/)([!#$&-;=?\-\[\]_a-z~%]+)/sim', '<a href="$1$2">$2</a>',
preg_replace('/(\s)((www\.)([!#$&-;=?\-\[\]_a-z~%]+))/sim', '$1http://$2', $string)
);