Ce face net/http.Cookie
Un cookie este o pereche nume-valoare pe care serverul o trimite browserului, iar browserul o trimite înapoi la fiecare cerere: așa țin minte site-urile sesiunea, limba sau coșul. http.SetCookie(w, &http.Cookie{...}) adaugă antetul Set-Cookie în răspuns, deci se apelează înainte de a scrie corpul.
r.Cookie("sesiune") citește cookie-ul primit; dacă lipsește, returnează eroarea http.ErrNoCookie. r.Cookies() le returnează pe toate.
Câmpuri importante: Path (pe ce căi se trimite, de obicei "/"), MaxAge (secunde de viață; negativ șterge cookie-ul), HttpOnly (JavaScript nu îl poate citi, protecție XSS), Secure (doar prin HTTPS) și SameSite (protecție CSRF).
Ce returnează
SetCookie: nimic. Request.Cookie: *http.Cookie și o eroare.
Exemple
Exemplul 1: Setarea și citirea unui cookie
package main
import (
"errors"
"fmt"
"net/http"
"net/http/httptest"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/limba", func(w http.ResponseWriter, r *http.Request) {
http.SetCookie(w, &http.Cookie{
Name: "limba",
Value: r.URL.Query().Get("l"),
Path: "/",
MaxAge: 30 * 24 * 3600,
HttpOnly: true,
SameSite: http.SameSiteLaxMode,
})
fmt.Fprint(w, "limba salvată")
})
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
c, err := r.Cookie("limba")
if errors.Is(err, http.ErrNoCookie) {
fmt.Fprint(w, "limba implicită: ro")
return
}
fmt.Fprint(w, "limba aleasă: ", c.Value)
})
rec := httptest.NewRecorder()
mux.ServeHTTP(rec, httptest.NewRequest("GET", "/limba?l=en", nil))
setCookie := rec.Header().Get("Set-Cookie")
fmt.Println("Set-Cookie:", setCookie)
rec = httptest.NewRecorder()
mux.ServeHTTP(rec, httptest.NewRequest("GET", "/", nil))
fmt.Println(rec.Body.String())
req := httptest.NewRequest("GET", "/", nil)
req.AddCookie(&http.Cookie{Name: "limba", Value: "en"})
rec = httptest.NewRecorder()
mux.ServeHTTP(rec, req)
fmt.Println(rec.Body.String())
}
Rezultat
Set-Cookie: limba=en; Path=/; Max-Age=2592000; HttpOnly; SameSite=Lax
limba implicită: ro
limba aleasă: en
Exemplul 2: Ștergerea unui cookie
Un cookie se șterge trimițându-l din nou cu același nume și cale și MaxAge negativ; Go îl scrie în antet ca Max-Age=0, adică „expiră acum”.
package main
import (
"fmt"
"net/http"
"net/http/httptest"
)
func main() {
iesire := func(w http.ResponseWriter, r *http.Request) {
http.SetCookie(w, &http.Cookie{Name: "sesiune", Value: "", Path: "/", MaxAge: -1})
fmt.Fprint(w, "te-ai delogat")
}
rec := httptest.NewRecorder()
iesire(rec, httptest.NewRequest("POST", "/iesire", nil))
fmt.Println(rec.Header().Get("Set-Cookie"))
fmt.Println(rec.Body.String())
}
Rezultat
sesiune=; Path=/; Max-Age=0
te-ai delogat
Greșeli frecvente
- Apelezi
http.SetCookiedupă ce ai scris corpul: antetul nu mai pleacă și cookie-ul nu este setat. - Pui în cookie date sensibile sau în care ai încredere (
admin=true, prețuri). Utilizatorul poate modifica orice cookie; păstrează doar un identificator de sesiune aleatoriu (vezicrypto/rand.Text). - Ștergi cookie-ul cu alt
Pathdecât cel cu care a fost creat: browserul îl consideră alt cookie și îl păstrează.
Comenzi înrudite
net/http.Header: Antetele unei cereri sau ale unui răspuns: Get citește, Set înlocuiește, Add adaugă încă o valoare, Del șterge.net/http.ResponseWriter: Interfața prin care handler-ul construiește răspunsul: antete (Header), cod de stare (WriteHeader) și corp (Write).crypto/rand.Text: Returnează un text aleatoriu sigur (26 de caractere A-Z și 2-7, cel puțin 128 de biți), gata de folosit ca token sau secret.