Apa itu Penguraian URL?
Penguraian URL adalah proses memecah Uniform Resource Locator menjadi komponen-komponen individualnya: protokol (scheme), hostname, port, pathname, parameter query, dan pengenal fragmen. Setiap URL mengikuti struktur yang didefinisikan oleh RFC 3986 dan WHATWG URL Standard. Sebuah URL parser membaca string mentah, mengidentifikasi setiap segmen berdasarkan karakter pemisahnya (://, :, /, ?, #, &, =), dan mengembalikannya sebagai bidang-bidang terpisah yang dapat diakses.
Browser melakukan penguraian URL setiap kali Anda mengetik alamat atau mengklik tautan. Konstruktor URL JavaScript, modul urllib.parse Python, dan paket net/url Go semuanya mengimplementasikan parser yang mengikuti aturan struktural yang sama. Mengurai URL adalah kebalikan dari encoding URL: alih-alih mengubah karakter untuk transport yang aman, Anda mengurai URL yang sudah terbentuk menjadi bagian-bagian penyusunnya.
URL tipikal seperti https://api.example.com:8080/v1/users?page=2&limit=10#section mengandung enam komponen yang berbeda. Karakter pemisah — ://, :, /, ?, &, =, dan # — adalah yang membuat penguraian menjadi deterministik: setiap karakter menandai batas dan memungkinkan parser mengekstrak bidang tanpa ambiguitas.
Mengapa Menggunakan URL Parser Online?
Memisahkan URL secara manual dengan mata rentan terhadap kesalahan, terutama ketika string mengandung karakter yang dikodekan, banyak parameter query, atau port non-standar. Alat ini mengurai URL menggunakan algoritma yang sesuai WHATWG — sama seperti yang digunakan browser — dan menampilkan setiap komponen dalam tabel yang jelas dan dapat disalin.
Kasus Penggunaan URL Parser
Referensi Komponen URL
Tabel di bawah menampilkan setiap properti yang dikembalikan oleh konstruktor URL JavaScript saat mengurai URL. Komponen yang sama ada dalam hasil urlparse Python, struct url.URL Go, dan output parse_url PHP, meskipun nama properti berbeda antar bahasa.
| Properti | Contoh | Deskripsi |
|---|---|---|
| protocol | https: | Scheme including the trailing colon |
| hostname | api.example.com | Domain name or IP address |
| port | 8080 | Port number (empty string if default) |
| pathname | /v1/users | Path starting with / |
| search | ?page=2&limit=10 | Query string including the leading ? |
| hash | #section | Fragment identifier including the leading # |
| origin | https://api.example.com:8080 | protocol + hostname + port |
| host | api.example.com:8080 | hostname + port |
| username | admin | Credentials before @ (rarely used in practice) |
| password | secret | Credentials before @ (avoid in production URLs) |
| href | (full URL) | The complete, serialized URL string |
WHATWG URL Standard vs RFC 3986
Dua spesifikasi mendefinisikan cara URL harus diurai. Keduanya sepakat tentang struktur dasar tetapi berbeda dalam kasus tepi — dan perbedaan itu biasanya menjadi penyebab ketika browser menangani URL secara berbeda dari yang dilakukan server Anda.
Dalam praktiknya, sebagian besar perbedaan muncul saat mengurai URL dengan nama domain internasional (IDN), scheme yang hilang, atau karakter yang tidak biasa. Parser WHATWG mengonversi hostname IDN ke Punycode secara otomatis, sementara parser RFC 3986 yang ketat mungkin menolaknya. Jika Anda menempelkan URL ke alat ini dan melihat hasil yang berbeda dari yang dihasilkan kode sisi server Anda, perbedaan WHATWG vs RFC kemungkinan besar adalah penyebabnya.
Contoh Kode
Setiap bahasa utama memiliki URL parser bawaan. Contoh di bawah mengurai URL yang sama dan mengekstrak komponen-komponennya. Perhatikan perbedaan penamaan kecil antar bahasa: Python menggunakan scheme alih-alih protocol, dan Go mengekspos RawQuery alih-alih search.
const url = new URL('https://api.example.com:8080/v1/users?page=2&limit=10#section')
url.protocol // → "https:"
url.hostname // → "api.example.com"
url.port // → "8080"
url.pathname // → "/v1/users"
url.search // → "?page=2&limit=10"
url.hash // → "#section"
// Iterate over query parameters
for (const [key, value] of url.searchParams) {
console.log(`${key} = ${value}`)
}
// → "page = 2"
// → "limit = 10"
// Modify and re-serialize
url.searchParams.set('page', '3')
url.toString()
// → "https://api.example.com:8080/v1/users?page=3&limit=10#section"from urllib.parse import urlparse, parse_qs
result = urlparse('https://api.example.com:8080/v1/users?page=2&limit=10#section')
result.scheme # → 'https'
result.hostname # → 'api.example.com'
result.port # → 8080
result.path # → '/v1/users'
result.query # → 'page=2&limit=10'
result.fragment # → 'section'
# Parse query string into a dict
params = parse_qs(result.query)
params['page'] # → ['2']
params['limit'] # → ['10']
# Reconstruct with modifications
from urllib.parse import urlencode, urlunparse
new_query = urlencode({'page': '3', 'limit': '10'})
urlunparse(result._replace(query=new_query))
# → 'https://api.example.com:8080/v1/users?page=3&limit=10#section'package main
import (
"fmt"
"net/url"
)
func main() {
u, err := url.Parse("https://api.example.com:8080/v1/users?page=2&limit=10#section")
if err != nil {
panic(err)
}
fmt.Println(u.Scheme) // → "https"
fmt.Println(u.Hostname()) // → "api.example.com"
fmt.Println(u.Port()) // → "8080"
fmt.Println(u.Path) // → "/v1/users"
fmt.Println(u.RawQuery) // → "page=2&limit=10"
fmt.Println(u.Fragment) // → "section"
// Query params as map
q := u.Query()
fmt.Println(q.Get("page")) // → "2"
fmt.Println(q.Get("limit")) // → "10"
}<?php $url = 'https://api.example.com:8080/v1/users?page=2&limit=10#section'; $parts = parse_url($url); $parts['scheme']; // → "https" $parts['host']; // → "api.example.com" $parts['port']; // → 8080 $parts['path']; // → "/v1/users" $parts['query']; // → "page=2&limit=10" $parts['fragment']; // → "section" // Parse query string into an array parse_str($parts['query'], $params); $params['page']; // → "2" $params['limit']; // → "10"