net/http.Header în Go

Antetele unei cereri sau ale unui răspuns: Get citește, Set înlocuiește, Add adaugă încă o valoare, Del șterge.

Sintaxă
type Header map[string][]string

func (h Header) Get(key string) string
func (h Header) Set(key, value string)
func (h Header) Add(key, value string)
func (h Header) Del(key string)

Ce face net/http.Header

http.Header este un map de la numele antetului la o listă de valori, pentru că un antet poate apărea de mai multe ori (de exemplu Set-Cookie). Îl găsești în r.Header (cererea), w.Header() (răspunsul de pe server) și resp.Header (răspunsul primit de client).

Get(cheie) returnează prima valoare sau "". Set(cheie, v) înlocuiește toate valorile cu v. Add(cheie, v) adaugă o valoare la cele existente. Del(cheie) șterge antetul. Toate patru nu țin cont de litere mari/mici: numele sunt aduse la forma canonică (content-type devine Content-Type). Pentru toate valorile unui antet folosește h.Values(cheie).

Ce returnează

Get: prima valoare sau "". Celelalte nu returnează nimic.

Exemple

Exemplul 1: Get, Set, Add, Del

package main

import (
	"fmt"
	"net/http"
)

func main() {
	h := http.Header{}
	h.Set("content-type", "text/html")        // numele devine Content-Type
	h.Set("Content-Type", "application/json") // Set înlocuiește
	h.Add("Accept-Language", "ro")
	h.Add("accept-language", "en;q=0.8") // Add adaugă încă o valoare
	h.Set("X-Depanare", "da")

	fmt.Println("Content-Type:   ", h.Get("CONTENT-TYPE"))
	fmt.Println("Accept-Language:", h.Get("Accept-Language"), "| toate:", h.Values("Accept-Language"))
	h.Del("x-depanare")
	fmt.Println("X-Depanare:     ", h.Get("X-Depanare") == "")
	fmt.Println("Map-ul complet: ", h)
}

Rezultat

Content-Type:    application/json
Accept-Language: ro | toate: [ro en;q=0.8]
X-Depanare:      true
Map-ul complet:  map[Accept-Language:[ro en;q=0.8] Content-Type:[application/json]]

Exemplul 2: Antete trimise și primite

Clientul trimite un antet Authorization; serverul răspunde cu antete proprii, citite apoi de client.

package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"
)

func main() {
	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("X-Utilizator", "token primit: "+r.Header.Get("Authorization"))
		w.Header().Add("Cache-Control", "no-store")
		w.Header().Add("Vary", "Authorization")
		w.Header().Add("Vary", "Accept-Language")
	}))
	defer srv.Close()

	req, _ := http.NewRequest("GET", srv.URL, nil)
	req.Header.Set("Authorization", "Bearer abc123")
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	resp.Body.Close()
	fmt.Println(resp.Header.Get("X-Utilizator"))
	fmt.Println(resp.Header.Get("Cache-Control"))
	fmt.Println(resp.Header.Values("Vary"))
}

Rezultat

token primit: Bearer abc123
no-store
[Authorization Accept-Language]

Greșeli frecvente

  • Citești direct din map cu un nume necanonic: h["content-type"] este gol, pentru că cheia salvată este Content-Type. Folosește Get.
  • Folosești Set pentru antete care trebuie să apară de mai multe ori: valorile anterioare se pierd. Folosește Add.
  • Modifici w.Header() după ce ai scris corpul: antetele au plecat deja.

Comenzi înrudite

  • net/http.ResponseWriter: Interfața prin care handler-ul construiește răspunsul: antete (Header), cod de stare (WriteHeader) și corp (Write).
  • net/http.Request: Structura unei cereri HTTP: metoda, URL-ul, antetele, corpul și contextul (Context()) care se anulează când clientul pleacă.
  • net/http.Cookie: Cookie descrie un cookie; SetCookie îl trimite clientului; Request.Cookie citește cookie-ul trimis de browser.
  • net/http.NewRequest: Construiește o cerere HTTP completă (orice metodă, antete, corp) care se trimite apoi cu Client.Do.