79
Tags:
php
Skrevet af
Bruger #3143
@ 04.01.2004
I denne artikel vil jeg beskrive nogle ting omkring HTTP headers, hvordan de virker, og hvordan de kan bruges. Jeg vil gennemgå nogle fejl i PHP, som jeg har erfaret, at mange laver, og forklare teorien bag. Det forudsættes at du i forvejen ved en lille smule om cookies og sessions.
Headers og HTTP
En kommunikation over HTTP forløber, simpelt skrevet, således:
En bruger klikker på et link på en webside. Herefter findes den server, hvor siden ligger på, og der skabes kontakt. Det vil jeg ikke komme nærmere ind på. Se eventuelt dk-hostmasters site (
http://www.dk-hostmaster.dk/dkhostcms/bs?pageid=77&action=cmsview) omkring DNS. Når der er kontakt mellem de to servere, sendes et HTTP request. Requestet behandles af serveren, og der sendes et response tilbage til klienten.
Request
Et HTTP request indeholder for det første adressen på den side, man vil besøge. For det andet indeholder den en række headers. Disse headers kan fx være post-data, cookies og info om browseren.
PostHvis man har submittet en form, der bruger post-method, sendes indholdet af felterne i headersne. (Hvis der bruges get-method, sendes de som en del af adresselinjen (URL’en) ) I PHP lægges disse data ind i en array-variabel, som hedder $_POST.
Eksempel: Vi sender følgende form af sted ved at trykke på knappen "Gør noget":
<form action="min_php_side.php" method="post">
<input type="text" name="felt1" value="en værdi">
<input type="text" name="felt2" value="en anden værdi">
<input type="submit" name="submit1" value="send">
<input type="submit" name="submit2" value="Gør noget">
</form>
Dataene fra denne form vil blive sendt af sted som request-headers, og PHP vil automatisk lave en variabel der ser sådan ud:
<?php
$_POST = array (
"felt1" => "en værdi",
"felt2" => "en anden værdi",
"submit2" => "Gør noget"
);
?>
Læg mærke til, at det kun er den submitknap, som trykkes på, der sendes med.
CookiesUdover post-variabler sendes også cookies med header-data. Det foregår på den måde, at din internetbrowser finder alle de cookies, som den URL, der requestes, har adgang til, og sætter dem ind som headers. Tænk dig derfor godt om, før du laver en cookie. Begræns antallet så meget som muligt, og lav dem så korte som muligt. Sørg for at afgrænse tiden og de sider, der har adgang til cookien, til hvad, der er nødvendigt. Jo flere cookies du laver, jo flere data skal der sendes med, hver gang en side loades. Så at gå i gang med at lave et par tusinde cookies er ikke nogen særlig god idé.
Cookies fra browseren vil i PHP blive lagt ind i variablen $_COOKIE fx:
<?php
$_COOKIE = array (
"cookie1" => "halløjsa",
"cookie2" => "hej hej",
"PHPSESSID" => "3ebd70ae76ee9a05ca3eca1b829a0ab1"
);
?>
Læg mærke til den sidste cookie.
SessionsMed sessions kan man gemme forskellige variabler på serveren for hver bruger. Mere herom senere. For så at identificere brugerne, kan man gemme en cookie hos hver bruger med et id. Det er dette id, der kan ses i den sidste cookie i eksemplet ovenfor.
Andre dataUdover post og cookies sendes der også en række andre headers med en request. Jeg vil lige nævne en af dem, HTTP_USER_AGENT. Her sendes en række informationer omkring brugerens browser. Fx i min browser ser den således ud:
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)
Der er også en lang række andre headers som denne, og de kan hentes i variablen $_SERVER. I denne variabel er der ikke kun headerdata, men også en række andre data. Her er et lille script til at se hvad den indeholder:
<table border=1>
<?php
foreach( $_SERVER as $key => $value ){
echo "<tr><td>$key<td>";
if( is_array ( $value ) ){
echo "<table border=1>";
foreach( $value as $key2 => $value2 ){
echo "<tr><td>$key2<td>$value2";
}
echo "</table>";
}
else{
echo $value;
}
}
?>
</table>
Response
Nu har vi kigget på HTTP requesten. Når der er sendt en request af sted, vil serveren behandle den, og i dette tilfælde vil PHP behandle vores side, før den sendes tilbage til webbrowseren i et HTTP response. Et response består først af response headers og derfter af en body, dit HTML dokument. Og her kommer det vigtige:
I et HTTP response sendes først headerinformation og derefter dit html-dokument.Er man først begyndt at sende noget af body-sektionen, kan man ikke redigere headers eller tilføje nye.
I PHP sendes headers til browseren, første gang der udskrives noget body-kode. Det er fordi body-kode sendes til browseren, efterhånden om det genereres. Det er en god ting, hvis man har et meget tidskrevende script, og man så kan starte med at sende noget til browseren, så brugeren kan se, at der sker noget. Indtil headers sendes, kan du frit oprette, redigere og slette dem.
CookiesDe headers man oftest har brug for, er headers til at sætte cookies. De kan laves automatisk ved hjælp af funktionen setcookie.
Eksempel:<?php
setcookie (
"navn",
//navnet på cookien
"værdi",
//cookiens værdi
time()+3600,
//tidspunkt, for hvornår cookien skal slettes
// time() er tiden nu, og 3600 er sekunder = 1 time
"sti/der/har/adgang/til/cookien/",
//den sti der skal have adgang til cookien
"domæne.der.har.adgang.til.cookien",
//det domæne der skal have adgang til cookien
0
)
?>
setcookie har 6 parametre. Det er kun nødvendigt at sætte det første. Som nævnt før er det en god ide at begrænse tiden, stien og domænet, til hvad der er brug for. Hvis tiden sættes til 0, vil cookien slettes når browseren lukkes. For at slette en cookie skal man lave en ny med samme informationer som den, man vil slette, og sætte sletningstidspunktet til en gang i fortiden. For mere information om setcookie, se PHP-manualen (
http://dk.php.net/setcookie).Cookies sættes altså i headers. Det er derfor ikke muligt at sætte flere cookies, når headers er sendt. Hvis man alligevel gør det, vil man få en fejlmeddelelse, der ligner:
[b]Warning:[/b] Cannot modify header information - headers already sent by
(output started at /sti/til/script.php:3) in [b]/sti/til/script.php[/b]
on line [b]4[/b]
Filen, der har fremkaldt denne fejl, ser således ud:
<?
setcookie("fejl"); //fejlkode
?>
Det ser måske ikke ud som om, der er sendt noget kode til browseren, men der er allerede sendt to linjeskift !! Derfor kan du ikke sætte denne cookie.
Løsningen er at flytte setcookie op i starten af scriptet. Hvis det ikke er muligt, kan du bruge ob_start() og ob_flush(), som omtales senere.
Det kan godt være svært at se, hvor fejlen er, selvom det står i fejlmeddelelsen, at det er i linje 3 (i eksemplet). Det kan som i eksemplet være linjeskift eller mellemrum, det kan være tekst fra inkluderede filer, og det kan være tekst fra fejlmeddelelser, der er kommet tidligere.
Det er ikke sikkert, at browseren modtager cookien, og brugeren kan vælge at slette den. Du kan ikke se om cookien er sat. Hvis du kunne, skulle denne information sendes i requesten, og den er allerede blevet sendt, før PHP overhovedet er begyndt at udføre scriptet, så det kan man ikke.
Du kan heller ikke se din cookie, før næste gang siden loades, fordi cookies, der er gemt, sendes med requestet og variablen $_COOKIE sættes før scriptet køres. Du kan dog selv sætte værdien ind i variablen hver gang du bruger setcookie:
<?php
setcookie ( "navn", "værdi" );
$_COOKIE ["navn"] = "værdi";
?>
Du skal stadigvæk huske på, at en cookie
ikke bliver sat ved at ændre i $_COOKIE variablen.
SessionsHvis du ikke ved hvad sessions er, er dette nok volapyk. Hvis du vil lære om sessions, kan du læse denne artikel. (
http://udvikleren.dk/article.php?aid=87&techid=6)Som tidligere nævnt bruger sessions cookies til at bestemme, hvilken bruger der besøger siden. Den gemmer et id i en cookie, når funktionen session_start() kaldes. Derfor er det vigtigt, at headers ikke er sendt lige som i cookies. Det er derfor altid en god idé at sætte denne funktion øverst i sit script. Husk også, at sessionen gælder for inkluderede sider, lige som alt andet. Du skal altså IKKE bruge session_start() igen i include-filer.
Lige gyldigt hvor mange filer på serveren, der inkluderes, sendes der kun et request og et response mellem serveren og klienten. Derfor skal session_start() kun bruges én gang.
Sessions bruges ofte til at lave login-systemer. Det er ofte mere sikkert end fx at gemme brugernavn og password i cookies. Dog betyder det, at alle, der besøger siden, vil få gemt en cookie. Det kan man forhindre ved at sætte session på følgende måde:
<?php
if ( isset ( $_COOKIE ["PHPSESSID"] ) ) session_start();
?>
Her startes session kun, hvis der er logget ind. Man skal så huske at kalde session_start(), når der tjekkes for brugernavn og password.
Det kan man mene, er en ligegyldig detalje, især fordi session cookies ofte har levetiden 0, det vil sige, at den slettes, når browseren lukkes, men jeg har nu alligevel valgt at tage den med.
Andre headersDer findes også en række andre headers. Disse kan ændres med funktionen header(). Du kan læse mere og funktionen og de forskellige headers i PHP-manualen. (
http://dk.php.net/header) Her kan du også læse om headres, der bestemmer, hvordan sider skal cashes.
LocationDen mest brugte header, som skal sættes med header() funktionen er nok location. Denne header sender brugeren automatisk videre til en anden side. Det kan fx se således ud:
<?php
header("Location: http://side.com/script.php");
?>
Location får browseren til at foretage et nyt request til den side, der er angivet. Den bruges ofte til at føre brugeren til en login-side, hvis brugeren besøger en beskyttet side uden at være logget ind.
Den bruges også nogen gange, til at tjekke om en cookie er blevet sat. Da der er sendt et response og et nyt request, skulle man mene, at cookien var sat. Det er dog ikke sikkert. Man kan ikke bestemme, hvilken rækkefølge headersne læses af browseren. Du ved derfor ikke, om din setcookie-header eller din location-header læses først. Derfor kan du risikere, at din cookie ikke er nået at blive sat, før den nye request sendes af sted.
Output bufferingMan skal som sagt sørge for at bruge header-funktionerne (setcookie, session_start og header), før man udskriver bare det mindste mellemrum til browseren. Er det ikke muligt, kan man bruge output buffering.
Det består først af funktionen ob_start(). Denne funktion sørger for, at alt, der udskrives til browseren, holdes tilbage, og derved at headers ikke sendes.
Når man har udført alle ændringer til headersne, kan man sende outputtet ved at bruge funktionen ob_flush(). Herved sendes headers også, og man kan ikke bruge setcookie(), session_start() og header() mere.
Det var så lidt om headers, og grunden til nogle af de fejlmeddelelser, man kan få når man bruger sessions og cookies. Håber det kan bruges.
Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.
Del også gerne artiklen med dine Facebook venner:
Kommentarer (11)
Velskrevet og velovervejet... Godt arbejde :o)
Bravo
5 fra mig
Rart med en artikel omkring dette emne
Der er rigtig mange nybegynder der ikke er så kendte med headers, så jeg tror det er godt med en artikel at henvise dem til.
5 herfra
god nok artikel, men hvad med lidt om hvordan den fil man egentlig sender ser ud? Altså bl.a. det med at i det browseren ser, der kommer der FØRST alle headerne, adskilt med linjeskift, og når headerne er sendt så kommer der 2 linjeskift og derefter kommer den egentlige fil, og mimetypen? Bør den ikke nævnes.
Og så ser jeg også at du bruger ob_flush(), hvorfor ikke ob_end_flush()? du skal da vel stoppe output bufferingen?
Elers god artikel, og et relevant emne, 4 herfra :-).
God artikel, men som du selv skriver "Det forudsættes at du i forvejen ved en lille smule om cookies og sessions"....artiklen burde nok ikke være sat til "Niveau: Nybegynder", men det er jo en mindre detalje ;-)
> god nok artikel, men hvad med lidt om hvordan den fil man egentlig sender ser ud?
Jeg ville ikke gøre artiklen for teoretisk, og så vidste jeg det heller ikke. (Ud over som skrevet, at headers sendes først)
> hvorfor ikke ob_end_flush()?
Det har du ret i. Jeg har aldrig selv brugt output buffering, så jeg fik ikke lige tænkt så meget over det.
> artiklen burde nok ikke være sat til "Niveau: Nybegynder"
Det synes jeg også selv...
God artikel.. Jeg får helt lyst til at lave et brugersystem.
Forklaret så man forstår det - og alligevel også lærer noget.
5 herfra.
Kanon artikel, den er virkelig velformuleret og lærerig indenfor området...
5 herfra.
Dét skal jeg sgu huske!
Har ikke læst artiklen, men før jeg læser den vil jeg lige vide. Hvad skal man bruge det til? (ikke for at være flabet :p) Mikl, en udvikler, har skrevet, at han mener man skal vide, hvad det skal bruges til, før man bevæger sig ud i det. Det kan jeg godt så pointen i.
Så var lige sød og skriv nogle ekspempler.
Vil sige når du siger "cookie sessions mm" så når man skal starte på sessions så skriver du vis man ikke kan sessions så skal man læse en artikel (linket virker ikke)
Du skal være
logget ind for at skrive en kommentar.