Co je parsování URL?
Parsování URL je proces rozdělení Uniform Resource Locatoru na jeho jednotlivé komponenty: protokol (schéma), hostname, port, cesta, parametry dotazu a identifikátor fragmentu. Každá URL se řídí strukturou definovanou standardy RFC 3986 a WHATWG URL Standard. Parser URL přečte surový řetězec, identifikuje každý segment podle oddělovačů (://, :, /, ?, #, &, =) a vrátí je jako samostatná, přístupná pole.
Prohlížeče provádějí parsování URL pokaždé, když zadáte adresu nebo kliknete na odkaz. JavaScript konstruktor URL, Python modul urllib.parse a balíček net/url v Go implementují parsery, které se řídí stejnými strukturálními pravidly. Parsování URL je inverzní operací k URL kódování: místo transformace znaků pro bezpečný přenos rozložíte již sestavené URL na části, ze kterých se skládá.
Typická URL jako https://api.example.com:8080/v1/users?page=2&limit=10#section obsahuje šest odlišných komponent. Oddělovací znaky — ://, :, /, ?, &, =, a # — jsou tím, co činí parsování deterministickým: každý z nich signalizuje hranici a umožňuje parseru extrahovat pole bez nejednoznačnosti.
Proč používat online URL parser?
Ruční rozdělování URL pohledem je náchylné k chybám, zejména pokud řetězec obsahuje zakódované znaky, více parametrů dotazu nebo nestandardní porty. Tento nástroj parsuje URL pomocí stejného algoritmu kompatibilního s WHATWG, který používají prohlížeče, a zobrazuje každou komponentu v přehledné tabulce s možností kopírování.
Případy použití URL parseru
Přehled komponent URL
Tabulka níže zobrazuje každou vlastnost vrácenou JavaScript konstruktorem URL při parsování URL. Stejné komponenty existují ve výsledku Python urlparse, struktuře url.URL v Go a výstupu PHP parse_url, přestože se názvy vlastností mezi jazyky liší.
| Vlastnost | Příklad | Popis |
|---|---|---|
| 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
Dvě specifikace definují způsob parsování URL. Shodují se na základní struktuře, ale liší se v hraničních případech — a tato odlišnost je obvykle příčinou, když váš prohlížeč zpracovává URL jinak než váš server.
V praxi se většina rozdílů projevuje při parsování URL s mezinárodními doménovými jmény (IDN), chybějícími schématy nebo neobvyklými znaky. Parser WHATWG automaticky převádí IDN hostname na Punycode, zatímco striktní parsery RFC 3986 je mohou odmítnout. Pokud vložíte URL do tohoto nástroje a uvidíte jiné výsledky než váš serverový kód, rozdíl mezi WHATWG a RFC je nejpravděpodobnější příčinou.
Ukázky kódu
Každý hlavní jazyk má vestavěný parser URL. Níže uvedené příklady parsují stejnou URL a extrahují její komponenty. Všimněte si drobných rozdílů v pojmenování napříč jazyky: Python používá scheme místo protocol a Go vystavuje RawQuery místo 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"