URL Parser & Pengdekode

Uraikan URL apa pun menjadi komponen-komponennya · protokol, host, port, jalur, parameter kueri, dan fragmen.

Anatomi URL

URL diurai menjadi enam bagian konseptual: scheme://userinfo@host:port/path?query#fragment. Scheme memberi tahu klien protokol mana yang akan digunakan (https, http, ftp, mailto, file, data) dan merupakan satu-satunya bagian yang selalu hadir. Komponen userinfo (username:password@) jarang dalam penggunaan modern; browser umumnya melucutinya dari URL yang ditampilkan karena itu telah menjadi vektor phishing sejak 1990-an. Host adalah lokasi jaringan: nama domain terdaftar, alamat IP (IPv4 dotted-quad atau IPv6 dalam tanda kurung siku), atau nama khusus seperti localhost. Port adalah port TCP/UDP (80 default untuk HTTP, 443 untuk HTTPS, dll.); ketika dihilangkan, default scheme berlaku. Path adalah hierarki yang dipisahkan-slash yang mengidentifikasi sumber daya dalam host. Query string (semuanya setelah ?) membawa pasangan kunci-nilai yang dipisahkan oleh &, digunakan untuk penyaringan, paginasi, pelacakan, pengiriman formulir. Fragment (semuanya setelah #) adalah satu-satunya bagian dari URL yang tidak pernah dikirim ke server: itu diproses sepenuhnya sisi-klien oleh browser untuk menggulir ke bagian tertentu atau, dalam aplikasi single-page, untuk menunjukkan status route.

Format query string sendiri memiliki cabang: tradisional ?key=value&key2=value2 dengan nilai percent-encoded per RFC 3986, vs konvensi form-encoded application/x-www-form-urlencoded yang lebih lama di mana + berarti spasi (awalnya untuk pengiriman formulir HTML). Sebagian besar parser menangani keduanya, tetapi konversinya asimetris: %20 selalu didekode menjadi spasi; + hanya didekode menjadi spasi di dalam query string, tidak pernah di dalam path. Ini adalah salah satu bug parsing URL paling umum di alam liar.

Sejarah Singkat URL

URL: awalnya "Universal Document Identifier," kemudian "Universal Resource Locator": ditemukan oleh Tim Berners-Lee antara memo "Information Management: A Proposal" Maret 1989 di CERN (yang dianotasi bos Mike Sendall "Vague but exciting") dan halaman web yang dapat dijelajahi publik pertama Agustus 1991. URL pertama kanonis adalah http://info.cern.ch/hypertext/WWW/TheProject.html, diposting 6 Agustus 1991. Diskusi IETF 1992 mengganti nama UDI menjadi URL untuk menghindari pertarungan kosakata. RFC 1738 ("Uniform Resource Locators"), ditulis oleh Berners-Lee, Masinter, dan McCahill, diterbitkan pada Desember 1994 sebagai sintaks URL formal pertama. RFC 2396 mengikuti pada Agustus 1998, menggeneralisasi URL ke konsep URI yang lebih luas. Spesifikasi kanonis saat ini adalah RFC 3986 ("URI Generic Syntax"), diterbitkan Januari 2005, diedit oleh Berners-Lee, Roy Fielding, dan Larry Masinter: STD 66 Internet Standard, tingkat kematangan tertinggi IETF. RFC 3986 adalah apa yang dituju setiap parser URL secara nominal. Dalam praktiknya browser modern menyimpang dari RFC 3986 dalam berbagai kasus tepi, itulah mengapa WHATWG memelihara URL Living Standard terpisah di url.spec.whatwg.org; spesifikasi WHATWG secara eksplisit bertujuan untuk menggusur RFC 3986 dan RFC 3987 seiring waktu, dan keduanya masih berbeda pada hal-hal seperti penanganan spasi trailing, set percent-encoding, dan normalisasi Unicode.

Karakter Tidak-Dicadangkan, Dicadangkan, dan Percent-Encoded

RFC 3986 §2.3 mendefinisikan karakter tidak-dicadangkan: satu-satunya karakter yang dijamin aman dalam komponen URI apa pun tanpa percent-encoding: A-Z, a-z, 0-9, hyphen (-), titik (.), underscore (_), dan tilde (~). 66 karakter total. Yang lainnya adalah karakter dicadangkan dengan makna struktural dalam beberapa komponen: gen-delims (:/?#[]@) dan sub-delims (!$&'()*+,;=): atau "lainnya" dan harus di-percent-encode jika muncul dalam URI. Percent-encoding (RFC 3986 §2.1) mengambil urutan byte dari karakter (dalam UTF-8 kecuali scheme menyatakan sebaliknya) dan menggantikan setiap byte dengan %HH di mana HH adalah nilai hex dua-digit byte. Jadi é yang di-encode UTF-8 (byte 0xC3 0xA9) menjadi %C3%A9; kata Rusia привет menjadi %D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82: dua byte per karakter, enam triplet %XX dan 36 karakter URL percent-encoded untuk enam huruf Sirilik.

Browser menampilkan path percent-encoded dalam dua cara: sebagian besar browser modern (Chrome, Firefox, Safari) men-decode dan merender glif Unicode asli di address bar ketika encoding adalah UTF-8 valid, tetapi menyalin bentuk percent-encoded literal ketika pengguna menyalin URL. Browser yang lebih lama dan banyak log web hanya menunjukkan bentuk percent-encoded, itulah mengapa "URL Unicode cantik" bisa menyesatkan: mereka terlihat indah di address bar dan jelek dalam teks apa pun di mana mereka dibagikan. RFC 3987 ("Internationalized Resource Identifiers", IRI), diterbitkan Januari 2005, memformalkan URL Unicode dalam bentuk yang tidak di-encode; Punycode (RFC 3492, Maret 2003) mendefinisikan bagaimana nama domain yang diinternasionalkan di-encode menjadi ASCII untuk DNS, label demi label: label tingkat-atas Cina 中国 menjadi xn--fiqs8s, sehingga example.中国 diselesaikan di tingkat DNS sebagai example.xn--fiqs8s. Demonstrasi kanonis adalah URL IRI Wikipedia: https://ja.wikipedia.org/wiki/東京 berfungsi di browser modern apa pun meskipun permintaan yang mendasarinya meng-encode path sebagai /wiki/%E6%9D%B1%E4%BA%AC.

WHATWG URL Standard: Apa yang Sebenarnya Dilakukan Browser

RFC 3986 IETF mengatakan satu hal; browser melakukan sesuatu yang sedikit berbeda. WHATWG (badan standar vendor browser) memelihara URL Living Standard terpisah di url.spec.whatwg.org yang menggambarkan mesin status algoritmik yang sebenarnya dijalankan browser: termasuk penanganan spasi awal, karakter kontrol, set percent-encoding yang bervariasi berdasarkan komponen, dan normalisasi Unicode. Spesifikasi WHATWG adalah apa yang diimplementasikan konstruktor URL browser (new URL(input)), dan apa yang Node.js, Deno, dan Bun semua konvergensikan untuk parsing URL built-in mereka. Parser URL Ada: ditulis dalam C++ oleh Yagiz Nizipli, Daniel Lemire, dan lainnya: menjadi parser yang sesuai-WHATWG yang menggerakkan parsing URL Node.js sejak Node.js 18.16.0 (April 2023), menggantikan path url.parse() yang lebih lama; itu secara terukur lebih cepat daripada setiap implementasi sebelumnya dan merupakan standar de facto untuk parsing URL kinerja-tinggi pada 2026. RFC 3986 dan spesifikasi WHATWG masih belum sepenuhnya didamaikan, dan divergensi historis masih muncul di path kode legacy dan versi runtime yang lebih lama.

Query String: dan API URLSearchParams

Query string secara teknis hanya "semuanya setelah ? dan sebelum #": spesifikasi tidak benar-benar mendefinisikan cara menafsirkannya. Konvensi ?key=value&key=value dengan pemisah & adalah konvensi, bukan persyaratan. Dalam praktiknya, dua format query string mendominasi: application/x-www-form-urlencoded (format pengiriman formulir HTML default, di mana + berarti spasi) dan konvensi query URI standar (di mana spasi selalu %20). API URLSearchParams browser (bagian dari URL Living Standard WHATWG, baseline di semua browser modern sejak sekitar 2017) menangani kedua format secara transparan untuk parsing dan memancarkan varian form-encoded saat stringifikasi. Kunci yang diulang adalah legal: ?tag=red&tag=blue&tag=green valid, dan URLSearchParams.getAll('tag') mengembalikan ['red', 'blue', 'green']. Framework web yang berbeda menangani kasus kunci-yang-diulang secara berbeda: Rails dan Express mengumpulkan kunci yang diulang ke dalam array, sementara PHP menimpa nilai sebelumnya dengan yang kemudian kecuali kunci menggunakan konvensi tanda kurung name[]: yang merupakan sumber konstan bug cross-framework dalam integrasi API.

Trik Parsing URL Umum

Kasus Penggunaan Umum

Privasi: URL Membawa Rahasia Nyata

URL umumnya tidak diperlakukan sebagai rahasia, tetapi mereka sering membawa data yang merupakan rahasia. URL callback OAuth menyertakan token akses. URL login magic-link menyertakan token autentikasi sekali pakai. Tautan reset kata sandi menyertakan token reset. URL API internal menyertakan hostname internal dan path routing yang mengungkapkan infrastruktur. Bahkan URL aplikasi biasa mengungkapkan perilaku pengguna melalui parameter query: istilah pencarian, pemilihan filter, ID profil, pengidentifikasi sesi. Header Referer membocorkan URL sebelumnya ke setiap situs yang ditautkan, dimitigasi oleh header Referrer-Policy yang diperkenalkan sebagai W3C Candidate Recommendation pada 2017 (default browser masih bervariasi). URL berakhir di log akses server, di riwayat browser, di bookmark browser, di log CDN, di pipeline analytics, di pratinjau tautan aplikasi chat. Parser URL sisi-server melihat setiap URL yang ditempel ke dalamnya; parser hanya-browser tidak. Untuk URL API internal, callback OAuth dengan token, tautan reset kata sandi, atau URL apa pun yang tidak ingin Anda salin ke hard drive orang asing, parser hanya-browser adalah arsitektur yang tepat. Verifikasi di tab Network DevTools saat Anda mengurai, atau bawa halaman offline (mode pesawat) setelah dimuat.

Pertanyaan yang Sering Diajukan

Bagian apa yang dikandung URL?

Enam bagian konseptual: scheme (https, http, ftp, mailto), userinfo (jarang dalam penggunaan modern, sebagian besar dilucuti oleh browser sebagai mitigasi-phishing), host (domain atau IP), port (default 80 untuk HTTP, 443 untuk HTTPS), path (hierarki yang dipisahkan-slash), query (pasangan kunci-nilai setelah ?), dan fragment (setelah #, tidak pernah dikirim ke server). Tata bahasa lengkapnya ada di RFC 3986 §3 (Januari 2005, STD 66) dan WHATWG URL Living Standard.

Bagaimana saya men-decode karakter URL-encoded?

Percent-encoding menggantikan karakter yang tidak aman dengan % diikuti oleh kode hex byte: spasi adalah %20, titik dua adalah %3A, garis miring depan adalah %2F, ampersand adalah %26, tanda at adalah %40. Karakter multi-byte UTF-8 dikodekan byte-demi-byte, sehingga é menjadi %C3%A9 (dua byte). Parser secara otomatis men-decode semua karakter percent-encoded dalam output yang ditampilkan. Fungsi JavaScript standar adalah encodeURIComponent() untuk meng-encode nilai individual dan decodeURIComponent() untuk men-decode.

Apa itu fragment URL?

Fragment (semuanya setelah #) adalah satu-satunya bagian dari URL yang diproses sepenuhnya sisi-klien: itu tidak pernah dikirim ke server web dalam permintaan HTTP. Tujuan asli: menggulir browser ke elemen anchor dengan ID itu. Penggunaan modern termasuk status route aplikasi single-page (#/dashboard/profile), token alur-implicit OAuth (sekarang tidak disarankan demi kode otorisasi dengan PKCE), dan navigasi halaman PDF (file.pdf#page=5). Karena fragment tidak mencapai server, mereka adalah tempat untuk menyimpan nilai yang seharusnya tidak muncul di log server.

Mengapa + kadang-kadang berarti spasi dan kadang-kadang berarti +?

Dua konvensi pengkodean ada. application/x-www-form-urlencoded (format pengiriman formulir HTML default) mengkodekan spasi sebagai +; percent-encoding standar (per RFC 3986) mengkodekan spasi sebagai %20. Keduanya valid dalam query string; hanya %20 yang valid dalam path dan fragment. URLSearchParams menangani keduanya secara transparan. Bug cross-context muncul ketika kode menggunakan encodeURIComponent (yang mengkodekan spasi sebagai %20) untuk parameter query yang server harapkan dalam bentuk form-encoded, atau sebaliknya.

Apakah ini menangani URL relatif?

Parser mengharapkan URL lengkap dengan scheme. Untuk path relatif seperti /api/users, tambahkan URL dasar (https://example.com/api/users) untuk mem-parse-nya. Beberapa parsing URL relatif (menyelesaikan terhadap URL dasar seperti yang dilakukan browser untuk atribut href) ada di roadmap: bentuk dua-argumen konstruktor URL WHATWG (new URL(relative, base)) menangani ini dan adalah apa yang harus digunakan kode produksi.

Apakah URL saya dikirim ke mana pun?

Tidak. Parsing berjalan sepenuhnya di browser Anda melalui konstruktor URL WHATWG: URL yang Anda tempel tidak pernah meninggalkan perangkat Anda. Verifikasi di tab Network DevTools saat Anda mengklik Parse, atau bawa halaman offline (mode pesawat) setelah dimuat. Aman untuk URL callback OAuth yang berisi token akses, tautan reset kata sandi yang berisi token sekali pakai, URL API internal yang mengungkapkan infrastruktur, atau URL apa pun yang tidak ingin Anda salin ke hard drive orang asing.

Alat terkait