Wat is URL-parsing?
URL-parsing is het proces waarbij een Uniform Resource Locator wordt opgesplitst in de afzonderlijke onderdelen: protocol (scheme), hostnaam, poort, padnaam, queryparameters en fragmentidentificator. Elke URL volgt een structuur die is vastgelegd in RFC 3986 en de WHATWG URL-standaard. Een URL-parser leest de ruwe tekenreeks, identificeert elk segment aan de hand van scheidingstekens (://, :, /, ?, #, &, =) en geeft ze terug als afzonderlijke, toegankelijke velden.
Browsers voeren URL-parsing uit bij elke adresinvoer of klik op een link. De JavaScript URL-constructor, Pythons urllib.parse-module en Go's net/url-pakket implementeren parsers die dezelfde structuurregels volgen. Een URL parsen is het omgekeerde van URL-codering: in plaats van tekens transformeren voor veilig transport, split je een al gevormde URL op in de samenstellende delen.
Een typische URL zoals https://api.example.com:8080/v1/users?page=2&limit=10#section bevat zes afzonderlijke onderdelen. De scheidingstekens — ://, :, /, ?, &, =, en # — maken het parsen deterministisch: elk teken markeert een grens en stelt de parser in staat velden zonder ambiguïteit te extraheren.
Waarom een online URL-parser gebruiken?
Een URL handmatig met het oog opsplitsen is foutgevoelig, zeker wanneer de tekenreeks gecodeerde tekens, meerdere queryparameters of niet-standaard poorten bevat. Dit hulpmiddel parseert de URL met hetzelfde WHATWG-conforme algoritme als browsers en toont elk onderdeel in een overzichtelijke, kopieerbare tabel.
Toepassingen van de URL-parser
Overzicht van URL-onderdelen
De onderstaande tabel toont alle eigenschappen die de JavaScript URL-constructor teruggeeft bij het parsen van een URL. Dezelfde onderdelen bestaan in Pythons urlparse-resultaat, Go's url.URL-struct en PHP's parse_url-uitvoer, hoewel eigenschapsnamen per taal verschillen.
| Eigenschap | Voorbeeld | Beschrijving |
|---|---|---|
| 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-standaard versus RFC 3986
Twee specificaties bepalen hoe URL's worden geparseerd. Ze zijn het eens over de basisstructuur, maar wijken af bij randgevallen — en die afwijking is doorgaans de oorzaak als uw browser een URL anders verwerkt dan uw server.
In de praktijk treden de meeste verschillen op bij URL's met internationale domeinnamen (IDN), ontbrekende schema's of ongebruikelijke tekens. De WHATWG-parser converteert IDN-hostnamen automatisch naar Punycode, terwijl strikte RFC 3986-parsers ze mogelijk afwijzen. Als u een URL in dit hulpmiddel plakt en andere resultaten ziet dan uw server-side code produceert, is het WHATWG-versus-RFC-verschil de meest waarschijnlijke oorzaak.
Codevoorbeelden
Elke grote programmeertaal heeft een ingebouwde URL-parser. De onderstaande voorbeelden parsen dezelfde URL en extraheren de onderdelen. Let op de kleine naamverschillen: Python gebruikt scheme in plaats van protocol, en Go stelt RawQuery beschikbaar in plaats van 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"