Hvordan du bruker cookies

Ansvarsfraskrivelse: Dette blogginnlegget handler om informasjonskapsler, på engelsk kjent som cookies. Informasjonskapsler smaker ikke godt. Men jeg har en oppskrift på mer smakfulle cookies også.

Utviklers ståsted

Først anbefaler jeg å lese gårsdagens blogginnlegg: «Hva er cookies?»

Det forrige innlegget handlet mest om bruksområder sett fra en sluttbrukers ståsted. Altså den som surfer rundt på nettet uten å ofre informasjonskapsler så mange tanker.

Dette innlegget vil derimot handle om cookies sett fra en utviklers ståsted.

Behandling av cookies kan gjøres i et utall forskjellige skript- og programmeringsspråk, og det finnes sikkert også et utall forskjellige fremgangsmåter. Jeg vil derfor bare dekke det mest grunnleggende.

Legg forresten merke til at jeg i dette innlegget referer til cookies, ikke informasjonskapsler slik som i det forrige innlegget. Det er fordi dette blogginnlegget er rettet mer mot de som tenker data når de hører ordet cookie, og ikke de som tenker på kjeks. Og også litt fordi informasjonskapsler er et pokker så langt ord å skrive!

Sette, lese, oppdatere og slette

Et nettsted kan:

  • Sette (eller plassere) en cookie i nettleseren din
  • Lese en cookie som er satt i nettleseren din
  • Oppdatere en cookie som er satt i nettleseren din
  • Slette en cookie som er satt i nettleseren din

Jeg bruker vanligvis både JavaScript og PHP til behandling av cookies, men vil bare gå gjennom noen veldig enkle eksempler for JavaScript her. Cookies er et omfattende fagfelt, og skal du gjøre noe skikkelig heftig anbefaler jeg videre lesning andre steder. Jeg kan også anbefale jQuery Cookie, en plugin til jQuery som gjør arbeidet med cookies svært mye enklere.

Slik setter du en cookie

I sin aller enkleste form settes en cookie slik:

<script>
document.cookie = 'mincookie=mittinnhold; expires=Thu, 26 Dec 2013 22:00:00 GMT; path=/';
</script>

Dette er en cookie med navnet mincookie. Innholdet er mittinnhold. Den utløper om nøyaktig 14 dager fra jeg skriver dette.

Å komme frem til «Thu, 26 Dec 2013 22:00:00 GMT» med JavaScript er ikke gjort i en håndvending. I scriptet nedenfor lager jeg et nytt datoobjekt med nåværende tidspunkt som utgangspunkt og legger til en hel haug med millisekunder. Faktisk legger jeg til 1 209 600 000 millisekunder, eller 14 dager for å gjøre det litt mer begripelig.

<script>
var datoObjekt = new Date();
datoObjekt.setTime(datoObjekt.getTime()+(14*24*60*60*1000));
var utlopsdato = datoObjekt.toUTCString();
</script>

14*24*60*60*1000 betyr altså 14 dager x 24 timer x 60 minutter x 60 sekunder x 1000 millisekunder. Skal du ha et år i stedet for 14 dager erstatter du bare 14 med 365.

Jeg konverterer så dette tallet til den tekststrengen jeg skal benytte som utløpsdato med toUTCString().

Bygger vi en funksjon ut av dette og setter det hele i system får vi et fungerende script for å sette en cookie:

<script>
function setteCookie(navn,innhold,dager) {
  var datoObjekt = new Date();
  datoObjekt.setTime(datoObjekt.getTime()+(dager*24*60*60*1000));
  var utlopsdato = datoObjekt.toUTCString();
  document.cookie = navn+'='+innhold+'; expires='+utlopsdato+'; path=/';
}

setteCookie('verdensbestecookie','sjokoladebiter',90);
</script>

Dette er en cookie med navnet «verdensbestecookie», innholdet «sjokoladebiter» og med utløp 90 dager frem i tid.

Slik leser du en cookie

Først må du være klar over at du bare kan lese en cookie som du selv (dvs. det domenet du opererer på) har satt. Vær samtidig oppmerksom på at for eksempel Google Analytics kan sette en cookie på ditt domene via deres JavaScript som du har lagt inn.

Jeg begynner igjen med et eksempel i sin aller enkleste form:

<script>
alert(document.cookie);
</script>

Dette eksempelet popper opp en dialogboks med innholdet i dine cookies. Altså dine cookies i flertall, ikke din ene cookie. Alle tilgjengelige cookies returneres altså.

Cookies returneres på dette formatet, med et semikolon som skiller hver cookie:
cookienavn1=cookieinnhold1; cookienavn2=cookieinnhold2

Jeg kan for eksempel få returnert to cookies:
enannencookie=karameller; verdensbestecookie=sjokladebiter

For å finne innholdet i den cookien du er ute etter må du skrive en funksjon. Denne funksjonen må, i mitt tilfelle, finne tekststrengen verdensbestecookie= og ikke minst hvor den befinner seg (hvilket tegn- eller bokstavnummer).

Av ren latskap tillater jeg må å referere en utmerket funksjon fra W3Schools som gjør nettopp dette:

<script>
function getCookie(c_name) {
  var c_value = document.cookie;
  var c_start = c_value.indexOf(" " + c_name + "=");
  if (c_start == -1) {
   c_start = c_value.indexOf(c_name + "=");
  }
  if (c_start == -1) {
   c_value = null;
  }
  else {
   c_start = c_value.indexOf("=", c_start) + 1;
   var c_end = c_value.indexOf(";", c_start);
   if (c_end == -1) {
    c_end = c_value.length;
   }
   c_value = unescape(c_value.substring(c_start,c_end));
  }
 return c_value;
}
</script>

Slik oppdaterer du en cookie

Enkelt!

Du gjør akkurat det samme som da du satte en cookie, beskrevet for to avsnitt siden. Alt du trenger å huske på er å gi den samme navn, så vil innholdet overskrives med nytt innhold og ny utløpsdato settes.

Slik sletter du en cookie

Å slette en cookie er like enkelt som å oppdatere innholdet i den.

Du setter samme cookie på nytt, men med utløpsdato tilbake i tid, for eksempel -1 dag. Du trenger heller ikke oppgi noe innhold som skal inn cookie, den skal jo uansett slettes.

Basert på JavaScript-funksjonen min lenger oppe sletter du en cookie slik:

<script>
setteCookie('verdensbestecookie','',-1);
</script>

Verdt å nevne: «Request overhead»

Når det er satt en cookie for ditt domene (og i aktuell «path», som jeg ikke har gått inn på her), vil denne alltid sendes med forespørselsen fra nettleseren din. Dette gjelder for hver eneste fil nettleseren din etterspør.

Dette betyr altså at når du åpner denne siden hvor jeg bruker cookies, så vil alle tilgjengelige cookies sendes fra din datamaskin og til mitt nettsted sammen med forespørselen din. Og det er ikke bare én forespørsel etter selve HTML-dokumentet, det er x antall andre elementer du også etterspør, slik som bilder og grafikk.

Dette kan potensielt være snakk om mye data, og i tillegg har mange sluttbrukere gjerne en lavere opplastingshastighet enn nedlastingshastighet.

Har du en cookie på 4 kB, og nettstedet ditt har rundt 100 elementer (her telles js-filer, bilder osv. med) så blir det fort opp i mot 400 kB ekstra data som må lastes opp (ikke ned) på hver eneste sidevisning.

Statisk innhold fra «cookiefritt» domene

En løsning på dette kan være å servere statisk innhold fra et «cookiefritt» domene, altså et domene hvor det ikke eksisterer noen cookies. I mitt tilfelle kunne jeg for eksempel ha servert deg alle bildefilene via bilder.hardcode.no i stedet for fra selve hardcode.no.

Redusere cookiestørrelsen

For å redusere filtyngden kan det også være en idé å bare lagre en unik ID i selve cookien, og så lagre alt innholdet i en database eller lignende på webserveren.

Så hvis jeg skal logge alle sidene du har besøkt på hardcode.no med cookies, så kan jeg enten lagre alt dette i en cookie, eller så kan jeg gi deg ID-en 123456789 og lagre all informasjonen i en database, som peker til nettopp din ID.

Cookies i praksis

Ved hjelp av cookies kan jeg se hvor mange ganger du har sett denne siden:

Og dette gjorde jeg slik, ved å kombinere de tingene jeg har gått gjennom overfor (pluss noe ekstra snadder, som innerHTML):

<p>Ved hjelp av cookies kan jeg se hvor mange ganger du har sett denne siden:</p>
<h3 id="antallganger"></h3>

<script>
	
function setteCookie(navn,innhold,dager) {
  var datoObjekt = new Date();
  datoObjekt.setTime(datoObjekt.getTime()+(dager*24*60*60*1000));
  var utlopsdato = datoObjekt.toUTCString();
  document.cookie = navn+'='+innhold+'; expires='+utlopsdato+'; path=/';
}


function getCookie(c_name) {
  var c_value = document.cookie;
  var c_start = c_value.indexOf(" " + c_name + "=");
  if (c_start == -1) {
   c_start = c_value.indexOf(c_name + "=");
  }
  if (c_start == -1) {
   c_value = null;
  }
  else {
   c_start = c_value.indexOf("=", c_start) + 1;
   var c_end = c_value.indexOf(";", c_start);
   if (c_end == -1) {
    c_end = c_value.length;
   }
   c_value = unescape(c_value.substring(c_start,c_end));
  }
 return c_value;
}

if(getCookie("telleverket")!=null)
 {
  var nyttantall = parseInt(getCookie("telleverket")) + 1;
  setteCookie('telleverket',nyttantall,365);
  document.getElementById('antallganger').innerHTML=nyttantall+' ganger!';
 }
else
 {
  setteCookie('telleverket',1,365);
  document.getElementById('antallganger').innerHTML='Bare en gang!';
 }

</script>
Svend Asbjørn Sylling, 12. desember 2013

Bloggen fra Sylling Hardcode