# URL

## Vad det är

En URL, förkortning av Uniform Resource Locator och i vardagligt tal kallad webbadress eller bara
länk, är en textrad som både namnger en resurs och talar om för programvara hur den hämtas: vilket
protokoll som ska talas, vilken maskin som ska tillfrågas och vad maskinen ska tillfrågas om.
Klistra in en i en webbläsare, en terminal eller en konfigurationsfil, så kan var och en av dem
agera på den utan ytterligare hjälp.

Uppbyggnaden bestäms av den generiska syntax som varje schema följer:

```text
https://shop.example.com:8443/orders/42?view=full#items

scheme     https
host       shop.example.com
port       8443
path       /orders/42
query      view=full
fragment   items
```

Schemat säger hur resursen nås, här HTTP över TLS. Värden och den valfria porten säger var, sökvägen
säger vilken resurs på den värden det gäller, och frågesträngen bär parametrar, oftast som par av
formen `name=value` som fogas ihop med `&`. Fragmentet efter `#` pekar in i resultatet, mot en
rubrik eller en position. Det tillhör klienten: webbläsaren skalar bort det innan förfrågan skickas,
så servern får aldrig veta vilken del av sidan läsaren skickades till.

Eftersom tecken som `/`, `?`, `#`, `&` och `=` har uppgifter i den strukturen måste vart och ett av
dem procentkodas när det förekommer som vanlig data: skrivas som `%` följt av två hexadecimala
siffror. Ett mellanslag blir `%20`, ett et-tecken `%26` och själva procenttecknet `%25`. Bokstäver
utanför ASCII färdas på samma sätt, som sina byte i UTF-8, och det är så å, ä och ö eller ukrainska
ord i en sökväg tar sig fram.

Är en URL samma sak som en URI? Nästan. En URI, en Uniform Resource Identifier, är vilken sträng som
helst i den syntaxen som identifierar något. En URL är den sorten som dessutom anger hur det går att
hitta, medan `urn:isbn:9780000000002` namnger en bok utan att ge något sätt att hämta den. RFC 3986
ber nya specifikationer att säga URI. WHATWG:s URL Standard, som webbläsarna följer, gick åt andra
hållet: den bestämde sig för URL som det enda ordet och tog på sig att beskriva vad verkliga
implementationer gör, med målet att ersätta RFC:n. De två är överens om vanliga adresser och skiljer
sig åt i gränsfallen, och det är värt att minnas när en webbläsare och ett serverbibliotek tolkar
samma udda sträng.

## Varför det spelar roll

En publicerad URL är ett löfte. Den hamnar i bokmärken, sökindex, mejl, tryckta broschyrer,
chattloggar och andras sidor, och ingen av de kopiorna uppdaterar sig själv. Att ändra adressen
senare bryter varenda en av dem, om inte den gamla adressen fortsätter att svara med en omdirigering
till den nya.

Därför är det användbara beslutet ett tidigt beslut: vad adressen byggs av. Allt som sannolikt
ändras är en dålig grund, vare sig det är en sidrubrik, ett kategoriträd, ett produktnamn eller en
filändelse som avslöjar dagens ramverk. En kort identifierare, eller en slug som lagras som data och
ändras med avsikt, håller. Det gör också en plan för vad som händer när en adress ändå måste flytta:
den gamla blir en permanent omdirigering i stället för en 404.

Det andra beslutet gäller vad som hålls utanför. RFC 9110 säger det rakt ut: adresser är gjorda för
att delas, inte för att skyddas. De skrivs till loggar i servrar och proxyservrar, sparas i
webbläsarens historik, kopieras in i webbanalys och skickas, beroende på policy, med i huvudet
`Referer` till det som sidan laddar härnäst. Sessionsidentifierare, token för återställning av
lösenord, API-nycklar och personuppgifter hör hemma i huvuden eller i förfrågans body.

Längden är en mindre fråga. HTTP-specifikationen rekommenderar att programvara godtar adresser på
minst 8 000 oktetter, vilket är generöst, men en frågesträng som bär ett helt formulär eller ett
serialiserat filter brukar slå i en kortare gräns någonstans längs kedjan innan den når dit.

## Så ser det ut i praktiken

Arbetet på den här webbplatsen behandlar adresser som data som lever längre än texten på sidan. När
[495 resultatsidor på tre språk genererades från en skrivskyddad SQLite-export](/sv/portfolio/generated-321-achievement-pages-from-a-sqlite-export-132/)
gällde det mest betydelsefulla beslutet adressen. Webbplatsen härledde tidigare en sidas URL från de
inledande orden i dess engelska påstående, så en rättad mening flyttade sidan i tysthet och bröt
varje länk till den. Adressen skrivs nu som data, en rad per adress och resultat: den första raden
är den aktuella, och varje senare rad är en avvecklad adress som webbplatsen publicerar som en
omdirigering. Varje adress som webbplatsen någonsin har publicerat svarar fortfarande.

En anteckning om mobilplånböcker visar vad som händer när en URL färdas inuti en annan.
[Phantom, Solflare och Backpack öppnar en dApp via universella länkar](/sv/notes/solana-mobile-wallet-deeplinks/)
som bär måladressen i sin egen sökväg och ursprunget som gör begäran i parametern `ref`, båda
skickade genom `encodeURIComponent`. Ett okodat `?` eller `&` i målet förstör tolkningen, och
plånboken öppnas på sin startskärm i stället för i webbläsarfliken. Det går ännu sämre för ett
gissat eget schema som `backpack://`: appen registrerar ingen rutt som matchar det, och användaren
hamnar på installationssidan.

Adresser fungerar också som identitet. När
[963 block av strukturerad data ersattes av en enda länkad graf](/sv/portfolio/replaced-963-structured-data-blocks-with-one-graph-138/)
skapades identifierarna för organisationen, webbplatsen och personen utifrån webbplatsens ursprung,
och listsidor publicerar sina poster enbart som URL:er. Det valet var uppmätt: att namnge posterna
på portföljens indexsida skulle ha inneburit 107 fullständiga påståenden och en komprimerad sida som
var 52 % större. Kontrollen som vaktar grafen säkerställer att varje URL som den nämner faktiskt
byggdes.

## Var det går fel

Fel i en URL brukar vara tysta. Adressen ser fortfarande rätt ut. Den pekar bara någon annanstans,
eller avslöjar mer än det var tänkt.

**Kodningen sker noll gånger eller två.** En returadress som läggs rå i en frågesträng, som i
`?next=/cart?item=4&size=m`, delas vid det andra `&`, och servern ser `size=m` som en egen
parameter. Att koda en redan kodad sträng gör `%20` till `%2520`, och sidan tar emot ett bokstavligt
`%20`. Koda varje komponent exakt en gång, i samma ögonblick som den placeras i adressen, med den
funktion som är avsedd för komponenter. I JavaScript är det `encodeURIComponent`. `encodeURI`
lämnar `?`, `&` och `#` orörda eftersom den förväntar sig en hel adress.

**En hemlighet åker med i frågesträngen.** En token för återställning av lösenord eller en
API-nyckel i adressen kopieras in i åtkomstloggar, webbläsarhistorik och webbanalys, och under en
tillåtande policy för referrer skickas den i `Referer` till varje tredje part som sidan laddar
något från. Lägg inloggningsuppgifter i ett huvud. När en token måste färdas i en länk, som i ett
mejl för återställning, gör den engångs och kortlivad och sätt en `Referrer-Policy` som håller den
hemma.

**En sida svarar på fem adresser.** `http` och `https`, med och utan `www`, med och utan avslutande
snedstreck, `/About` och `/about`. Schema och värd är per definition skiftlägesokänsliga, medan
sökvägen är skiftlägeskänslig om inte servern bestämmer något annat. Sökmotorer delar upp sidans
ställning mellan kopiorna, cachar lagrar var och en för sig och webbanalysen räknar dem separat.
Välj en form, omdirigera permanent från alla andra former till den och ange den som kanonisk URL.

**En relativ länk löses upp mot fel bas.** En referens som `img/logo.png` ersätter allt efter det
sista snedstrecket i den aktuella sökvägen. På `/docs/guide` blir den `/docs/img/logo.png`, och på
`/docs/guide/` blir den `/docs/guide/img/logo.png`. Ett enda avslutande snedstreck flyttar varje
relativ länk på sidan. Länkar som utgår från roten och börjar med `/` slipper problemet.

**Logiken hänger på fragmentet.** Omdirigeringar på serversidan, åtkomstloggar och webbanalys som
läser förfrågan ser allt fram till `#` och stannar där. Allt som måste nå servern hör hemma i
sökvägen eller i frågesträngen.

## Läs mer

- [RFC 3986: Uniform Resource Identifier (URI): Generic Syntax](https://www.rfc-editor.org/rfc/rfc3986)
  — grammatiken, procentkodningen, upplösningen av relativa referenser och normaliseringen.
- [WHATWG URL Standard](https://url.spec.whatwg.org/) — tolkningsalgoritmen som webbläsarna
  implementerar, steg för steg.
- [RFC 3987: Internationalized Resource Identifiers](https://www.rfc-editor.org/rfc/rfc3987)
  — hur adresser skrivna i vilket skriftsystem som helst översätts till procentkodade byte.
- [RFC 8820: URI Design and Ownership](https://www.rfc-editor.org/rfc/rfc8820)
  — varför den som äger en värd, och ingen annan, bestämmer hur dess sökvägar ser ut.
- [RFC 9110, section 17.9](https://www.rfc-editor.org/rfc/rfc9110#section-17.9)
  — säkerhetsanmärkningen om känslig information i adresser.

<https://engineer.company/sv/glossary/url/>
