Ga naar hoofdinhoud

URI's en URL's

Een URL (Uniform Resource Locator) is het adres van een bron op het web. Ze zegt niet alleen welke bron je wil, maar ook waar en hoe je ze bereikt. Elk onderdeel van dat adres wordt door een andere partij gebruikt: de browser, DNS, de transportlaag, de server, en soms enkel de pagina zelf.

Anatomie van een URL​

scheme://gebruiker@host:poort/pad?query#fragment

Een voorbeeld waarin alles voorkomt:

https://api.voorbeeld.be:8443/v1/gebruikers?rol=admin&pagina=2#resultaten
OnderdeelWaardeWie gebruikt hetWat het doet
schemehttpsBrowserBepaalt het protocol en de standaardpoort
hostapi.voorbeeld.beDNSWordt vertaald naar een IP-adres
poort8443TransportlaagZegt welk programma op die machine antwoordt
pad/v1/gebruikersServerWelke bron je vraagt
queryrol=admin&pagina=2ServerExtra parameters: filteren, sorteren, pagineren
fragmentresultatenEnkel de browserNaar welk stuk van de pagina gescrold wordt
Anatomie van een URL: https://api.voorbeeld.be:8443/v1/gebruikers?rol=admin&pagina=2#resultaten, met per onderdeel wie het gebruikt: browser (scheme en fragment), DNS (host), transportlaag (poort) en server (pad en query)https://api.voorbeeld.be:8443/v1/gebruikers?rol=admin&pagina=2#resultatenschemehostpoortpadqueryfragmentBrowserscheme · fragmentKiest het protocol en daarmeede standaardpoort (443 bij https).Scrolt naar #resultaten, maarstuurt het fragment nooit mee.DNShostVertaalt api.voorbeeld.be naareen IP-adres. Het enige stukvan de URL dat DNS ooit ziet.TransportlaagpoortZegt welk programma op diemachine antwoordt. Weggelatenals het de standaardpoort is.Serverpad · queryWelke bron je vraagt, en metwelke parameters: filteren,sorteren, pagineren.Eén adres, vier lezers. Elk onderdeel wordt door een andere partij gebruikt.

Scheme​

Het scheme bepaalt welk protocol gebruikt wordt, en daarmee ook de standaardpoort:

SchemeStandaardpoortWaarvoor
http80Onversleuteld web
https443Versleuteld web, zie HTTPS & TLS
ws / wss80 / 443WebSockets: een open verbinding in twee richtingen
ftp21Bestandsoverdracht (verouderd)
mailto–Opent een mailprogramma in plaats van een verbinding
Daarom staat er zelden een poort in je adresbalk

Komt de poort overeen met de standaard van het scheme, dan mag je ze weglaten: https://ap.be en https://ap.be:443 zijn identiek. Bij je dev server staat de poort er wél bij, omdat 5173 geen standaard is.

Host​

De host is de domeinnaam of het IP-adres van de server. Dit is het enige stuk dat via DNS vertaald wordt naar een adres waar het netwerk mee overweg kan.

https://www.ap.be/onderwijs -> DNS zoekt enkel www.ap.be op

De host komt ook nog eens apart mee in het request, als de Host-header. Dat is nodig omdat één server honderden domeinen kan bedienen. Zie HTTP-headers.

Pad​

Het pad identificeert de bron op die server. Soms komt het letterlijk overeen met een bestand op schijf, vaker wordt het door de applicatie geïnterpreteerd:

/over-ons.html -> misschien een echt bestand
/producten/42 -> een applicatie zoekt product 42 op in een databank
/v1/gebruikers -> een API-route, zie JSON & REST

Voor de browser maakt dat verschil niets uit: hij vraagt gewoon dat pad op. Hoe paden in API's een vaste betekenis krijgen, lees je in JSON, REST & clientverzoeken.

Query-parameters​

Alles na het vraagteken zijn query-parameters: sleutel-waardeparen, gescheiden door &.

https://voorbeeld.be/producten?categorie=laptops&max_prijs=1000&pagina=2

Ze horen bij het filteren, sorteren en pagineren van een bron, niet bij het uitvoeren van een actie. ?id=42 om een product op te vragen kan, maar ?actie=verwijderen hoort niet: daarvoor bestaan methoden.

Query-parameters gaan mee naar de server en verschijnen dus ook in serverlogs. Zet er nooit wachtwoorden of tokens in.

Speciale tekens: URL-encoding​

Een URL mag geen spaties of accenten bevatten. Die worden gecodeerd als % plus de hexadecimale waarde van de byte:

TekenGecodeerd
spatie%20 (in een query soms +)
é%C3%A9
&%26
/%2F
https://voorbeeld.be/zoek?q=caf%C3%A9%20antwerpen

Dat é twee bytes wordt, komt rechtstreeks uit tekstcodering: UTF-8 slaat dat teken op als C3 A9.

Zelf coderen hoef je bijna nooit

Gebruik de ingebouwde functies in plaats van zelf tekens te vervangen:

encodeURIComponent('café antwerpen') // 'caf%C3%A9%20antwerpen'
curl --get --data-urlencode "q=café antwerpen" https://voorbeeld.be/zoek

Fragment​

Het fragment (#resultaten) verwijst naar een plek binnen de pagina. Het wordt nooit naar de server gestuurd: het blijft volledig aan de browserkant.

Dat kan je zelf nakijken. Open de Network tab, ga naar een pagina met een anker, en bekijk het request: in de startlijn staat het pad zonder het fragment. Zie Netwerkverkeer bekijken.

URI, URL, URN

Een URI identificeert een bron. Een URL doet dat én zegt waar en hoe je ze vindt. Elke URL is dus een URI, maar niet omgekeerd. In de praktijk van webontwikkeling gebruik je vrijwel altijd URL's, en worden de termen door elkaar gebruikt.

Absolute en relatieve URL's​

In HTML gebruik je zelden een volledige URL. Een relatieve verwijzing wordt door de browser aangevuld met de huidige pagina:

In je HTMLOp pagina https://voorbeeld.be/blog/artikel wordt dat
https://cdn.be/logo.pnghttps://cdn.be/logo.png (absoluut, ongewijzigd)
/img/logo.pnghttps://voorbeeld.be/img/logo.png (vanaf de root)
logo.pnghttps://voorbeeld.be/blog/logo.png (naast de pagina)
../logo.pnghttps://voorbeeld.be/logo.png (één map omhoog)

De klassieke fout is de derde regel: je verplaatst een pagina naar een andere map en al je afbeeldingen geven plots 404. In de Network tab zie je meteen welk adres de browser er dan van maakte.

Test jezelf​

1. Welk deel van `https://voorbeeld.be/producten?id=42#reviews` bereikt de server nooit?

2. Waarom staat er `:5173` in `http://localhost:5173` en niet in `https://ap.be`?

3. Je zoekt naar `caf&bar`. Wat gebeurt er met de `&` in de query?

Onthoud
  • Een URL bestaat uit scheme · host · poort · pad · query · fragment.
  • Elk onderdeel heeft een eigen afnemer: de host gaat naar DNS, de poort naar de transportlaag, pad en query naar de server, het fragment blijft bij de browser.
  • Standaardpoorten (80 voor http, 443 voor https) mag je weglaten.
  • Query-parameters dienen om te filteren en te pagineren, niet om acties uit te voeren.
  • Speciale tekens worden URL-gecodeerd; gebruik encodeURIComponent() in plaats van dat zelf te doen.