Hoppa till innehållet

URL

adressen som anger var något finns

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:

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 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 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 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

Ordlista