ResponseWriter va *Request obyektlari
Har bir Go handleri ikki argument oladi: w http.ResponseWriter va r *http.Request. Birinchisi orqali klientga javob yoziladi. Ikkinchisida klient yuborgan so‘rov haqidagi barcha ma’lumot bor.
Buni pochta bo‘limiga o‘xshatish mumkin. r — sizga kelgan xat: konvertida kimdan kelgani va qayerga yuborilgani yozilgan, ichida esa xatning o‘zi bor. w — javob xati uchun bo‘sh konvert va qog‘oz.
*http.Request — kelgan so‘rov
http.Request — struct. Handlerga uning ko‘rsatkichi (*http.Request) beriladi. Eng ko‘p ishlatiladigan maydonlar:
| Maydon yoki metod | Nima beradi | Misol qiymat |
|---|---|---|
r.Method |
HTTP metodi | "POST" |
r.URL.Path |
Yo‘l | "/books/42" |
r.URL.Query() |
Query parametrlar | ?page=2 → page: [2] |
r.Header |
So‘rov sarlavhalari | Content-Type: application/json |
r.Body |
So‘rov tanasi | JSON, forma yoki fayl |
r.Host |
So‘ralgan host | "localhost:8080" |
r.RemoteAddr |
Klient manzili | "127.0.0.1:53422" |
r.ContentLength |
Tana hajmi, bayt | 57 |
r.Context() |
So‘rovga bog‘langan context | — |
r.PathValue("id") |
Yo‘ldagi parametr (Go 1.22+) | "42" |
Misol: so‘rov haqidagi ma’lumotni qaytarish
Metod: GET
Yo‘l: /books
Query: page=2
Host: localhost:8080
Klient: 127.0.0.1:53422
User-Agent: curl/8.5.0
r.UserAgent() — r.Header.Get("User-Agent") ning qisqa shakli.
Sarlavhalarni o‘qish
r.Header turi — http.Header, aslida map[string][]string. Bitta sarlavha bir necha qiymatga ega bo‘lishi mumkin, shuning uchun qiymat slice ko‘rinishida saqlanadi.
ct := r.Header.Get("Content-Type") // birinchi qiymat yoki ""
langs := r.Header.Values("Accept-Language") // barcha qiymatlar
Get sarlavha nomining harf katta-kichikligiga qaramaydi: content-type va Content-Type bir xil ishlaydi. Go nomlarni ichida kanonik ko‘rinishga keltiradi.
Warning
r.Header["content-type"] ko‘rinishida map’dan to‘g‘ridan-to‘g‘ri o‘qish ishlamaydi, chunki kalit Content-Type shaklida saqlangan. Doim Get yoki Values metodidan foydalaning.
So‘rov tanasini o‘qish
r.Body turi io.ReadCloser. Tana oqim (stream) ko‘rinishida keladi, shuning uchun uni faqat bir marta o‘qish mumkin.
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, "tanani o‘qib bo‘lmadi", http.StatusBadRequest)
return
}
Server tomonida r.Bodyni yopish shart emas, server buni o‘zi bajaradi. Klient tomonidagi resp.Body esa albatta yopilishi kerak.
Tana hajmini cheklash muhim. Aks holda kimdir bir necha gigabaytlik so‘rov yuborib, server xotirasini to‘ldirib qo‘yishi mumkin:
Limitdan oshsa, o‘qish xato qaytaradi. JSON tanani to‘g‘ri o‘qish Request body parsing darsida alohida ko‘riladi.
Forma ma’lumotlari
HTML forma application/x-www-form-urlencoded formatida yuboriladi. Uni o‘qish uchun r.ParseForm() va r.FormValue() ishlatiladi:
func login(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
http.Error(w, "forma noto‘g‘ri", http.StatusBadRequest)
return
}
email := r.PostFormValue("email") // faqat tanadan
page := r.FormValue("page") // tanadan yoki URL query'dan
fmt.Fprintln(w, email, page)
}
PostFormValue qiymatni faqat so‘rov tanasidan oladi. FormValue esa tanaga ham, URL query’ga ham qaraydi. Qiymat qayerdan kelishi muhim bo‘lsa, PostFormValue aniqroq.
Cookie’larni o‘qish
c, err := r.Cookie("session_id")
if errors.Is(err, http.ErrNoCookie) {
http.Error(w, "session topilmadi", http.StatusUnauthorized)
return
}
fmt.Fprintln(w, "Session:", c.Value)
r.Cookie cookie topilmasa, http.ErrNoCookie xatosini qaytaradi.
So‘rov contexti
Har bir so‘rovning o‘z contexti bor. Klient ulanishni uzsa yoki server to‘xtasa, bu context bekor bo‘ladi. Uni database so‘rovlari va tashqi API chaqiruvlariga uzatish kerak. Bu mavzu Context bilan ishlash darsida alohida ko‘riladi.
http.ResponseWriter — javob yozish
ResponseWriter — interfeys. Uning uchta metodi bor:
Header() http.Header // javob sarlavhalari
WriteHeader(statusCode int) // status kodni yuborish
Write([]byte) (int, error) // tanani yozish
Javob yozish tartibi
HTTP javobi tarmoq orqali qat’iy tartibda yuboriladi: avval status qatori, keyin sarlavhalar, oxirida tana. Shu sababli handlerda ham tartib shunday bo‘lishi kerak:
1. w.Header().Set(...) → sarlavhalarni tayyorlash
2. w.WriteHeader(kod) → status va sarlavhalar yuboriladi
3. w.Write(...) → tana yoziladi
Misol
HTTP/1.1 201 Created
Content-Type: application/json
Location: /books/7
Date: Wed, 30 Sep 2026 10:00:00 GMT
Content-Length: 34
{"id":7,"title":"O‘tkan kunlar"}
curl -i javob sarlavhalarini ham ko‘rsatadi. Date va Content-Length sarlavhalarini Go o‘zi qo‘shdi.
Tartib buzilsa nima bo‘ladi?
Write yoki WriteHeader chaqirilgan zahoti sarlavhalar klientga yuboriladi. Shundan keyin ularni o‘zgartirib bo‘lmaydi.
func notogri(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("salom")) // 200 OK avtomatik yuborildi
w.Header().Set("Content-Type", "application/json") // ta’sir qilmaydi
w.WriteHeader(http.StatusCreated) // ta’sir qilmaydi
}
Oxirgi qatorda Go serverning logiga ogohlantirish yozadi:
Bu ogohlantirish ko‘pincha handlerda return unutilganini bildiradi:
if err != nil {
http.Error(w, "xato", http.StatusBadRequest)
// return yo‘q — kod davom etadi
}
w.WriteHeader(http.StatusOK) // superfluous WriteHeader
Info
WriteHeader chaqirilmasa, birinchi Write paytida avtomatik 200 OK yuboriladi. Content-Type o‘rnatilmagan bo‘lsa, Go tananing birinchi 512 baytiga qarab turini taxmin qiladi. API’da bu taxminga ishonmang, Content-Typeni doim o‘zingiz belgilang.
Set, Add va Del
w.Header().Set("Cache-Control", "no-store") // mavjud qiymatni almashtiradi
w.Header().Add("Vary", "Accept-Encoding") // yangi qiymat qo‘shadi
w.Header().Add("Vary", "Origin") // endi ikki qiymat bor
w.Header().Del("X-Powered-By") // o‘chiradi
Tanani yozishning turli usullari
ResponseWriter io.Writer interfeysini qanoatlantiradi. Shu sababli unga turli yo‘llar bilan yozish mumkin:
w.Write([]byte("matn")) // baytlar
io.WriteString(w, "matn") // satr
fmt.Fprintf(w, "Salom, %s", ism) // formatlangan matn
json.NewEncoder(w).Encode(data) // JSON
Cookie o‘rnatish
http.SetCookie(w, &http.Cookie{
Name: "session_id",
Value: "abc123",
Path: "/",
MaxAge: 3600,
HttpOnly: true,
Secure: true,
SameSite: http.SameSiteLaxMode,
})
http.SetCookie javobga Set-Cookie sarlavhasini qo‘shadi. Sarlavha bo‘lgani uchun uni ham WriteHeader va Writedan oldin chaqirish kerak. Cookie parametrlarining ma’nosi Session va Token-based auth farqi darsida tushuntiriladi.
Hammasi bitta misolda
Quyidagi handler so‘rovni o‘qiydi, tekshiradi va turli holatlarda turli javob qaytaradi:
Content-Type noto‘g‘ri bo‘lsa, 415 Unsupported Media Type qaytadi. Tana 1024 baytdan oshsa, 413 Request Entity Too Large qaytadi. Har bir xato holatidan keyin return bor. Shu sababli handler xatodan keyin davom etib, ikkinchi marta javob yozmaydi.
Xulosa
*http.Requestichida metod, URL, sarlavhalar, tana, cookie va context bor.r.Bodyoqim, uni faqat bir marta o‘qish mumkin. Hajminihttp.MaxBytesReaderbilan cheklang.http.ResponseWriterga yozish tartibi: sarlavhalar →WriteHeader→Write.- Birinchi
WriteyokiWriteHeaderdan keyin sarlavhalarni o‘zgartirib bo‘lmaydi. - Xato javobini yozgandan keyin
returnqilishni unutmang.
Keyingi darsda so‘rovni yo‘l va metodga qarab kerakli handlerga yo‘naltirish, ya’ni URL routing bilan shug‘ullanamiz.