Jeg vedder på at du har hatt en bug der en URL med mellomrom eller spesialtegn ødela noe. Kanskje et & i en søkestreng forårsaket merkelig oppførsel. Eller du så %20 i en URL og lurte på hva det var. La oss rydde opp i alt dette.
Hvorfor URL-er trenger koding
URL-er kan bare inneholde et begrenset sett med tegn. RFC 3986-spesifikasjonen definerer "ikke-reserverte" tegn som alltid er trygge: A-Z, a-z, 0-9, -, _, . og ~. Alt annet — mellomrom, &, =, ?, ikke-ASCII-tegn som ñ eller 日本語 — må prosentkodes.
Hvordan prosentkoding fungerer
Det er rett frem: ta tegnets UTF-8-byteverdi og representer hver byte som % etterfulgt av to heksadesimale sifre.
Eksempler:
- Mellomrom →
%20 &→%26=→%3Dé→%C3%A9(to byte i UTF-8)日→%E6%97%A5(tre byte i UTF-8)
Så Hello World blir Hello%20World i en URL-sti.
Feil nummer 1: dobbel koding
Dette er den vanligste URL-kodingsfeilen jeg ser, og den er subtil. Du koder en streng, sender den til en funksjon som koder den igjen. Nå blir %20 (et allerede kodet mellomrom) til %2520 fordi %-tegnet selv blir kodet.
Eksempel på problemet:
Løsningen: kod verdier én gang, på riktig nivå. Ikke kod ting som allerede er kodet.
Plusstegn vs. %20 — Ja, det er forvirrende
I URL-spørrestrenger kan mellomrom være enten + eller %20. +-konvensjonen kommer fra HTML-skjemakoding (application/x-www-form-urlencoded). I URL-stier er bare %20 gyldig.
Så https://example.com/hello world → stien kodes til https://example.com/hello%20world
Men https://example.com/search?q=hello world → spørringen kan være ?q=hello+world eller ?q=hello%20world
encodeURI vs. encodeURIComponent
JavaScript gir deg to funksjoner, og å bruke feil er en klassisk feil:
encodeURI()— Koder en hel URL. Lar:,/,?,#,&,=stå urørt fordi de er strukturelle deler av URL-en.encodeURIComponent()— Koder en URL-komponent (som en spørreparameterverdi). Koder OGSÅ:,/,?,#,&,=fordi de kan være del av dataene.
Tommelfingerregel: bruk encodeURIComponent() for verdier, aldri for hele URL-er. MDN-dokumentasjonen forklarer forskjellen utmerket.
Andre programmeringsspråk
- Python:
urllib.parse.quote()for stier,urllib.parse.urlencode()for spørrestrenger — dokumentasjon her - Java:
URLEncoder.encode()(bruker+for mellomrom — pass på!) - PHP:
urlencode()for spørrestrenger,rawurlencode()for stier
Raske tips
- Kod alltid parameter-verdier, aldri hele URL-er
- Dekod én gang på mottakersiden — ikke send kodede verdier gjennom flere lag
- Test med grensetilfeller: mellomrom,
&,=,#, ikke-ASCII-tegn og emoji
Bygge URL-er trygt i JavaScript
Den riktige måten å konstruere URL-er med spørreparametere er å bruke de innebygde URL- og URLSearchParams-API-ene. De håndterer all koding for deg:
Legg merke til hvordan URLSearchParams bruker + for mellomrom (HTML-skjemakodingskonvensjon) og koder & i verdien riktig slik at den ikke forveksles med & som separerer parametere. Dette er mye tryggere enn strengsammensetning.
Vanlige URL-kodingsfeller
1. Kode hele URL-en i stedet for bare verdiene. Hvis du kjører encodeURIComponent() på en hel URL, vil den kode ://, /, ? og &-tegnene — noe som gjør URL-en helt ubrukelig. Kod bare individuelle parameterverdier.
2. Glemme å kode hash-fragmenter. #-tegnet i en URL starter en fragmentidentifikator. Hvis dataene dine inneholder # og du ikke koder det, forsvinner alt etter det fra serverens perspektiv. Serveren ser aldri fragmentidentifikatorer — de er kun på klientsiden.
3. Ikke håndtere internasjonale domenenavn (IDN). Domenenavn med ikke-ASCII-tegn som example.日本 trenger spesiell håndtering kalt Punycode-koding. Dette er separat fra prosentkoding og gjelder kun vertsnavndelen av URL-en.
4. Kode mellomrom inkonsistent. Noen deler av systemet ditt kan kode mellomrom som + og andre som %20. Dette fungerer vanligvis bra for dekoding, men kan forårsake problemer med URL-sammenligning og caching. Velg én konvensjon og hold deg til den.
Prosentkoding hurtigreferanse
| Tegn | Kodet | Hvorfor det trenger koding |
| Mellomrom | %20 eller + | Ikke tillatt i URL-er |
& | %26 | Separerer spørreparametere |
= | %3D | Separerer nøkkel fra verdi |
? | %3F | Starter spørrestreng |
# | %23 | Starter fragmentidentifikator |
% | %25 | Selve escape-tegnet |
/ | %2F | Stiseparator |
@ | %40 | Brukes i userinfo-seksjonen |
URL-koding i forskjellige kontekster
URL-koding er ikke bare for nettleser-URL-er. Du vil støte på det i disse vanlige situasjonene:
- API-forespørsler: Spørreparametere i REST API-kall trenger riktig koding, spesielt hvis de inneholder brukerinndata
- Omdirigerings-URL-er: Når du sender en retur-URL som parameter (som
?redirect=https://...), må hele omdirigerings-URL-en kodes som en verdi - OAuth-flyter: OAuth-callback-URL-er og state-parametere er notorisk vanskelige fordi de involverer flere lag av URL-koding
- Deep links: Mobile deep links følger de samme URL-kodingsreglene, men noen plattformer har tilleggskrav
Feilsøking av URL-kodingsproblemer
Når noe går galt med URL-koding, her er min feilsøkingssjekkliste:
1. Sjekk for dobbel koding — Se etter %25 i URL-en, noe som betyr at en % ble kodet to ganger
2. Sjekk den rå forespørselen — Bruk nettleserens DevTools Network-fane for å se nøyaktig hvilken URL som ble sendt, før nettleseren viser den dekodede versjonen
3. Sammenlign kodet vs. dekodet — Lim inn den problematiske URL-en i en dekoder for å se hva den faktisk inneholder
4. Sjekk serversidedekoding — Noen rammeverk dekoder URL-parametere automatisk, og å gjøre det manuelt oppå det forårsaker problemer
Anatomien til en URL
OK, la oss ta et skritt tilbake. Før vi dykker dypere inn i koding, trenger du faktisk å forstå hva en URL er laget av. Jeg vet, jeg vet — du har brukt URL-er hele karrieren din. Men jeg vedder på at du ikke kjenner alle delene ved deres offisielle navn. De fleste utviklere gjør det ikke, og det er der kodingsforvirringen starter.
I følge RFC 3986 har en URL denne strukturen:
La meg gå gjennom hver del:
- Scheme (
https,ftp,mailto) — Protokollen. Ingen koding nødvendig her, det er alltid ASCII-bokstaver. - Authority — Dette inkluderer den valgfrie
user:password@(som du i praksis aldri bør bruke i 2026), verten (domenenavn eller IP), og et valgfritt portnummer. - Path (
/search/results) — Den hierarkiske delen. Skråstreker/separerer segmenter. Innenfor hvert segment må du kode spesialtegn, men du koder IKKE selve skråstrekene. - Query (
?q=hello&lang=en) — Nøkkel-verdi-par etter?.&separerer par,=separerer nøkler fra verdier. Du koder nøklene og verdiene, men ikke de strukturelle&og=. - Fragment (
#section-2) — Delen etter#. Denne er interessant — den sendes aldri til serveren. Den er rent klientsiden. Men du må fortsatt kode spesialtegn inni den.
Her er det som forvirrer folk: forskjellige deler av URL-en har forskjellige kodingsregler. En / er helt fin i stien (den er en separator!) men trenger å kodes som %2F hvis den dukker opp inne i en spørreparameterverdi. Et @-tegn er greit i authority-seksjonen men bør kodes i stien. Dette er grunnen til at universelle kodingsfunksjoner forårsaker så mange feil.
Tenk på det slik: URL-en er en setning med grammatikkregler. Spesialtegnene er tegnsetting. Du ville ikke kodet et komma som faktisk brukes som et komma — du koder bare et komma som er del av dataene og kan forveksles med tegnsetting.
encodeURI vs. encodeURIComponent: JavaScripts minefelt
Greit, dette temaet gjør meg helt gal fordi jeg ser utviklere gjøre det feil HELE TIDEN. JavaScript gir deg to kodingsfunksjoner, og de høres nesten identiske ut, men å bruke feil vil ødelegge dagen din.
La meg legge det frem tydelig:
encodeURI() er designet for å kode en hel URL. Den koder usikre tegn men lar de strukturelle være — ting som :, /, ?, #, &, =, @. Fordi hvis du koder en hel URL, vil du åpenbart ikke ødelegge URL-strukturen.
encodeURIComponent() er designet for å kode en enkelt verdi som går inn i en URL. Den koder ALT unntatt bokstaver, sifre og - _ . ~. Dette inkluderer :, /, ?, #, &, = — fordi når disse dukker opp i en verdi, er de data, ikke struktur.
Her er en sammenligning som gjør det krystallklart:
| Tegn | encodeURI() | encodeURIComponent() |
: | : (uendret) | %3A |
/ | / (uendret) | %2F |
? | ? (uendret) | %3F |
# | # (uendret) | %23 |
& | & (uendret) | %26 |
= | = (uendret) | %3D |
@ | @ (uendret) | %40 |
| Mellomrom | %20 | %20 |
é | %C3%A9 | %C3%A9 |
Nå blir det skummelt. Se hva som skjer når du bruker feil:
Og den motsatte feilen er like ille:
Den gylne regelen: encodeURIComponent for verdier, encodeURI for hele URL-er. Eller enda bedre, bare bruk URL API-et og la nettleseren håndtere det. Seriøst, URL- og URLSearchParams-klassene finnes av en grunn. Se MDN encodeURIComponent-dokumentasjonen og MDN encodeURI-dokumentasjonen for alle detaljene.
URL-koding i forskjellige programmeringsspråk
JavaScript er ikke det eneste språket med forvirrende URL-kodingsfunksjoner. Hvert språk har sine egne særheter, og jeg tuller ikke, noen av dem er enda mer forvirrende enn JavaScripts par.
Python — Faktisk ganske fornuftig, når du finner riktig modul:
Java — Her blir det rart. URLEncoder ble designet for HTML-skjemakoding, ikke generell URL-koding. Så mellomrom blir + i stedet for %20:
C# — .NET gir deg faktisk de riktige verktøyene, men det finnes omtrent fem forskjellige metoder og de gjør alle litt forskjellige ting:
PHP — Å, PHP. Selvfølgelig har du to funksjoner med nesten identiske navn som gjør litt forskjellige ting:
Go — Rent og fornuftig, som Go pleier å være:
Konklusjonen? Hvert språk håndterer + vs. %20-temaet forskjellig, og hvert språk har minst én funksjon som vil overraske deg. Sjekk alltid dokumentasjonen for språket du jobber med. Ikke anta at det fungerer likt som i JavaScript.
Unicode i URL-er: Det ville vesten
OK, her blir det VIRKELIG interessant. Hva skjer når du putter ikke-ASCII-tegn i en URL? Altså, hva om du vil ha en URL med japansk, arabisk eller — jeg tuller ikke — emoji?
Svaret involverer to helt forskjellige systemer, og å blande dem er en klassisk feil.
For sti- og spørredelene: Du bruker prosentkoding. Ta tegnets UTF-8-bytes og kod hver enkelt. Så café blir caf%C3%A9. Nettleseren din gjør dette automatisk og viser deg vanligvis den pene versjonen i adressefeltet, men under panseret sender den den prosentkodede versjonen.
For domenenavn: Prosentkoding brukes IKKE. I stedet finnes det et vilt system kalt Punycode. Det konverterer Unicode-domenenavn til ASCII-kompatible strenger som starter med xn--.
Sjekk dette:
café.com→xn--caf-dma.commünchen.de→xn--mnchen-3ya.de例え.jp→xn--r8jz45g.jp
Hvorfor to forskjellige systemer? Fordi DNS (systemet som gjør domenenavn om til IP-adresser) ble bygget på 1980-tallet og støtter kun ASCII. Så de måtte finne opp en måte å stappe Unicode inn i ASCII-strenger — og Punycode er den oppfinnelsen. Sti- og spørredelene av en URL, derimot, håndteres av webservere som kan håndtere prosentkodede bytes.
Det finnes faktisk en hel spesifikasjon for Unicode i URL-er kalt IRI (Internationalized Resource Identifiers) definert i RFC 3987. En IRI er i bunn og grunn en URL som tillater Unicode-tegn direkte. Nettlesere konverterer IRI-er til URI-er bak kulissene.
Og ja, emoji-domener finnes. 💩.la er et ekte domene (eller var det på et tidspunkt). Det Punycode-kodes til xn--ls8h.la. Jeg anbefaler ikke å bruke emoji-domener til noe seriøst, men det er et morsomt bevis på at systemet fungerer.
En fallgruve med Unicode i URL-er: forskjellige Unicode-representasjoner av det "samme" tegnet. For eksempel kan é representeres som ett enkelt kodepunkt (U+00E9) eller som e + et kombinerende aksenttegn (U+0065 + U+0301). Disse produserer forskjellige prosentkodede strenger! WHATWG URL-standarden anbefaler NFC-normalisering, men ikke alle systemer følger dette konsekvent.
Dobbel koding: Feilen som hjemsøker drømmene dine
Jeg nevnte dobbel koding tidligere, men det fortjener sitt eget dypdykk fordi denne feilen sannsynligvis har kastet bort flere kollektive utviklertimer enn noe annet URL-relatert problem. Vært der, gjort det — flere ganger.
Her er det grunnleggende scenariet:
Hva skjedde? Når du koder hello%20world en gang til, blir %-tegnet kodet til %25. Så %20 blir %2520. Serveren ser den bokstavelige strengen %20 i stedet for et mellomrom.
Dette høres opplagt ut når jeg skriver det slik, men i ekte kodebaser er det utrolig snikende. Her er scenariene der dobbel koding biter deg:
Proxy-kjeder. Du sender en forespørsel til server A, som videresender den til server B. Hvis begge servere koder URL-en, bam — dobbelt kodet. API-gatewayer som Kong, AWS API Gateway eller nginx reverse proxyer er vanlige syndere.
Omdirigeringskjeder. Bruker går til side A, blir omdirigert til side B med en ?returnUrl=...-parameter, og side B omdirigerer igjen med retur-URL-en som parameter. Hver omdirigering kan re-kode URL-en. Etter tre omdirigeringer er URL-en din trippelkodet og helt ødelagt.
Rammeverk-"hjelpere". Noen web-rammeverk koder URL-parametere automatisk. Hvis du manuelt koder før du sender til rammeverket, får du dobbel koding. Jeg har sett dette skje med Spring Boot, Express.js-mellomvare og Djangos URL-reversering.
Hvordan oppdager du dobbel koding? Se etter %25 i URL-en. Det er et prosenttegn som har blitt kodet, noe som vanligvis betyr at noe ble kodet to ganger. Hvis du ser %2520, er det et dobbeltkodet mellomrom. Hvis du ser %253D, er det et dobbeltkodet =-tegn.
Slik fikser du det:
Det beste forsvaret er å etablere klare grenser i koden din: kod på kantene (rett før du sender en HTTP-forespørsel, eller rett før du konstruerer en URL for visning), og send rå, ukodede strenger overalt ellers internt.
URL-lengdebegrensninger og hva du gjør med dem
Her er noe som vil overraske deg: HTTP-spesifikasjonen selv definerer IKKE en maksimal URL-lengde. RFC 3986 sier at URL-er bør ha "ubegrenset lengde". Men den virkelige verden er uenig.
Forskjellige komponenter i kjeden har sine egne begrensninger, og den korteste vinner:
| Komponent | Maks URL-lengde |
| Internet Explorer (RIP) | 2 083 tegn |
| Chrome, Firefox, Safari | ~65 000+ tegn |
| Apache (standard) | 8 190 tegn |
| Nginx (standard) | 8 192 tegn |
| IIS (standard) | 16 384 tegn |
| AWS ALB | 8 192 tegn |
| Cloudflare | 32 768 tegn |
Den gamle 2 083-tegnsbegrensningen fra IE styrte alt. Selv om IE i praksis er død nå, behandler noen utviklere og verktøy den fortsatt som evangelium. Men i praksis kan de fleste moderne stacker håndtere mye lengre URL-er.
Likevel, bare fordi du KAN lage en 65 000 tegn lang URL betyr ikke at du BØR. Her er noen reelle grunner til å holde URL-er korte:
- Serverlogger. Mange loggingssystemer kutter lange URL-er, noe som gjør feilsøking til et mareritt.
- Kopier og lim inn. Brukere kopierer og deler URL-er. Superlange URL-er brekker i e-poster, chatmeldinger og dokumenter.
- SEO. Søkemotorer anbefaler generelt å holde URL-er under 2 000 tegn.
- Caching. Noen CDN- og proxy-cachenøkkelbegrensninger er URL-baserte. Lengre URL-er = flere cache-bommerter.
Så hva gjør du når URL-en din blir for lang? Glad du spør:
1. Bruk POST i stedet for GET. Hvis du sender mye data, legg det i forespørselskroppen. Forespørselskroppen har ingen praktisk størrelsesbegrensning. Dette er den vanligste løsningen for komplekse søkeskjemaer med mange filtre.
2. Bruk URL-forkortere eller referanse-ID-er. Generer et kort token som kartlegger til det fulle parametersettet lagret på serversiden. Så i stedet for /search?filter1=abc&filter2=def&filter3=... får du /search/saved/abc123.
3. Komprimer parameterne dine. Noen apper base64-koder en komprimert JSON-blob og putter den i URL-en. Ikke pent, men det fungerer. Du ser dette i verktøy som Grafana-dashboard-URL-er.
Skjemakoding: application/x-www-form-urlencoded
La oss snakke om elefanten i rommet som gjør URL-koding enda mer forvirrende: HTML-skjemakoding. Når du sender et HTML-skjema med method="POST", koder nettleseren skjemadataene med et format kalt application/x-www-form-urlencoded. Og dette formatet er NESTEN det samme som standard prosentkoding, men med én nøkkelforskjell som driver alle gale.
Mellomrom blir + i stedet for %20.
Det er det. Det er hovedforskjellen. Men, herregud, den forårsaker forvirring.
Hvorfor finnes denne forskjellen? Historiske grunner, selvfølgelig. HTML-skjemakodingsspesifikasjonen er eldre enn URL-kodingsspesifikasjonen, og den brukte + for mellomrom fordi... vel, noen syntes det så penere ut på 90-tallet. Og nå sitter vi fast med det for alltid.
Når du sender et HTML-skjema, sender nettleseren en Content-Type: application/x-www-form-urlencoded-header, og serveren vet å tolke + som mellomrom. Men hvis du bygger URL-er manuelt i JavaScript og bruker + for mellomrom i stidelen, vil serveren se bokstavelige plusstegn. Morsomme tider.
Her er det viktig i praksis:
Og så er det multipart/form-data, som er et helt annet beist. Når skjemaet ditt inkluderer filopplasting (), bytter nettleseren til multipart/form-data-koding, som bruker grenser for å separere felt i stedet for &-tegn. Den bruker ikke URL-koding i det hele tatt — hver del har sine egne headere og kropp. Hvis du noen gang har prøvd å manuelt parse en multipart-forespørsel, kjenner du smerten.
Det praktiske rådet: bruk URLSearchParams for spørrestrenger og skjemadata. Bruk FormData for filopplasting. Ikke prøv å kode disse tingene for hånd med mindre du virkelig, virkelig må.
Prøv det selv
Jobber du med URL-er som ser feil ut? Lim dem inn i vår URL-dekoder for å se de faktiske tegnene. Trenger du å kode en verdi før du putter den i en URL? URL-koderen håndterer det umiddelbart. Og for å bryte ned komplekse URL-er i komponentene deres, bruk URL-parseren for å se hver del tydelig.