GoDasturchi
HTTP Status Codes Done Right

HTTP Status Codes Done Right

HTTP status kodlarini to'g'ri qo'llash

Svetofor faqat UCH RANGDA gapiradi (qizil, sariq, yashil), lekin HAR BIR haydovchi ularni BIR XIL tushunadi — chunki ma'no QAT'IY belgilangan. HTTP status kodlari ham xuddi shunday "universal til": 404 HAR DOIM "topilmadi", 409 HAR DOIM "ziddiyat" degani. Agar server "topilmadi" holatida 200 qaytarsa ("muvaffaqiyatli" degan ma'noda), bu — svetoforning QIZIL chirog'ida "yur" deyishga o'xshaydi: mijoz kutubxonalari (HTTP client'lar), monitoring tizimlari — BARCHASI adashadi.

example.go
package main

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

var (
	ErrNotFound   = errors.New("resurs topilmadi")
	ErrValidation = errors.New("validatsiya xatosi")
	ErrConflict   = errors.New("bunday resurs allaqachon mavjud")
)

// statusFor — xato TURIGA qarab, TO'G'RI HTTP status kodini tanlaydi
func statusFor(err error) int {
	switch {
	case errors.Is(err, ErrNotFound):
		return http.StatusNotFound
	case errors.Is(err, ErrValidation):
		return http.StatusUnprocessableEntity
	case errors.Is(err, ErrConflict):
		return http.StatusConflict
	default:
		return http.StatusInternalServerError
	}
}

func handle(w http.ResponseWriter, err error) {
	if err == nil {
		w.WriteHeader(http.StatusOK)
		fmt.Fprint(w, "ok")
		return
	}
	w.WriteHeader(statusFor(err))
	fmt.Fprint(w, err.Error())
}

func main() {
	for _, err := range []error{nil, ErrNotFound, ErrValidation, ErrConflict} {
		rec := httptest.NewRecorder()
		handle(rec, err)
		fmt.Println(rec.Code, rec.Body.String())
	}
}

Sentinel xatolar (ErrNotFound, ErrValidation, ErrConflict — "Sentinel Errors" darsini eslang) va errors.Is — biznes mantiq ("bu resurs topilmadimi?") bilan HTTP QATLAMI ("qaysi status kod?") ni ALOHIDA saqlaydi: biznes kod HECH QACHON http paketini bilmaydi, FAQAT error qaytaradi; statusFor esa BITTA joyda, xatoni HTTP tiliga TARJIMA qiladi.

Har bir status — ANIQ ma'noga ega: 404 Not Found — so'ralgan narsa YO'Q; 409 Conflict — so'rov O'ZI to'g'ri, lekin joriy HOLAT bilan ZID (masalan bir xil ISBN'li kitob YARATISHGA urinish); 422 Unprocessable Entity — so'rov TUZILISHI to'g'ri, lekin QIYMATLAR noto'g'ri; 500 Internal Server Error — bu ODDIY holatlar EMAS, dasturdagi KUTILMAGAN nosozlik.

>_ Exercise

Avtorizatsiya xatosi uchun yangi holat qo'shing.

  • ErrUnauthorized = errors.New("avtorizatsiya talab qilinadi") sentinel xatosini qo'shing
  • statusFor ichida errors.Is(err, ErrUnauthorized) holatida http.StatusUnauthorized (401) qaytaring
  • scenarios ro'yxatiga ErrUnauthorized va errors.New("kutilmagan xato") (noma'lum xato) ni ham qo'shing, barcha 6 holatni chop eting

Stuck? Reveal a hint to help you.

Hints (0/3)

Key Takeaway

Key Takeaway:

To'g'ri status kod tanlash — biznes xatosini (sentinel error) bitta markaziy statusFor funksiyasi orqali aniq HTTP koddga TARJIMA qilishdan iborat; noma'lum/kutilmagan xatolar har doim 500 ga tushadi, aniqlanganlar esa o'z ANIQ kodiga ega bo'ladi.

NEXT UP

Pagination: Limit & Offset

OUTPUT

$ go run main.go
Kodingizni ishga tushiring

HTTP Status Codes Done Right

HTTP status kodlarini to'g'ri qo'llash

Svetofor faqat UCH RANGDA gapiradi (qizil, sariq, yashil), lekin HAR BIR haydovchi ularni BIR XIL tushunadi — chunki ma'no QAT'IY belgilangan. HTTP status kodlari ham xuddi shunday "universal til": 404 HAR DOIM "topilmadi", 409 HAR DOIM "ziddiyat" degani. Agar server "topilmadi" holatida 200 qaytarsa ("muvaffaqiyatli" degan ma'noda), bu — svetoforning QIZIL chirog'ida "yur" deyishga o'xshaydi: mijoz kutubxonalari (HTTP client'lar), monitoring tizimlari — BARCHASI adashadi.

example.go
package main

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

var (
	ErrNotFound   = errors.New("resurs topilmadi")
	ErrValidation = errors.New("validatsiya xatosi")
	ErrConflict   = errors.New("bunday resurs allaqachon mavjud")
)

// statusFor — xato TURIGA qarab, TO'G'RI HTTP status kodini tanlaydi
func statusFor(err error) int {
	switch {
	case errors.Is(err, ErrNotFound):
		return http.StatusNotFound
	case errors.Is(err, ErrValidation):
		return http.StatusUnprocessableEntity
	case errors.Is(err, ErrConflict):
		return http.StatusConflict
	default:
		return http.StatusInternalServerError
	}
}

func handle(w http.ResponseWriter, err error) {
	if err == nil {
		w.WriteHeader(http.StatusOK)
		fmt.Fprint(w, "ok")
		return
	}
	w.WriteHeader(statusFor(err))
	fmt.Fprint(w, err.Error())
}

func main() {
	for _, err := range []error{nil, ErrNotFound, ErrValidation, ErrConflict} {
		rec := httptest.NewRecorder()
		handle(rec, err)
		fmt.Println(rec.Code, rec.Body.String())
	}
}

Sentinel xatolar (ErrNotFound, ErrValidation, ErrConflict — "Sentinel Errors" darsini eslang) va errors.Is — biznes mantiq ("bu resurs topilmadimi?") bilan HTTP QATLAMI ("qaysi status kod?") ni ALOHIDA saqlaydi: biznes kod HECH QACHON http paketini bilmaydi, FAQAT error qaytaradi; statusFor esa BITTA joyda, xatoni HTTP tiliga TARJIMA qiladi.

Har bir status — ANIQ ma'noga ega: 404 Not Found — so'ralgan narsa YO'Q; 409 Conflict — so'rov O'ZI to'g'ri, lekin joriy HOLAT bilan ZID (masalan bir xil ISBN'li kitob YARATISHGA urinish); 422 Unprocessable Entity — so'rov TUZILISHI to'g'ri, lekin QIYMATLAR noto'g'ri; 500 Internal Server Error — bu ODDIY holatlar EMAS, dasturdagi KUTILMAGAN nosozlik.

>_ Exercise

Avtorizatsiya xatosi uchun yangi holat qo'shing.

  • ErrUnauthorized = errors.New("avtorizatsiya talab qilinadi") sentinel xatosini qo'shing
  • statusFor ichida errors.Is(err, ErrUnauthorized) holatida http.StatusUnauthorized (401) qaytaring
  • scenarios ro'yxatiga ErrUnauthorized va errors.New("kutilmagan xato") (noma'lum xato) ni ham qo'shing, barcha 6 holatni chop eting

Stuck? Reveal a hint to help you.

Hints (0/3)

Key Takeaway

Key Takeaway:

To'g'ri status kod tanlash — biznes xatosini (sentinel error) bitta markaziy statusFor funksiyasi orqali aniq HTTP koddga TARJIMA qilishdan iborat; noma'lum/kutilmagan xatolar har doim 500 ga tushadi, aniqlanganlar esa o'z ANIQ kodiga ega bo'ladi.

NEXT UP

Pagination: Limit & Offset