GoDasturchi
Content Negotiation

Content Negotiation

Kontent kelishuvi (content negotiation)

Restoran ofitsianti mijozdan "qaysi tilda menyu kerak?" deb SO'RAYDI va shu tilda menyu OLIB KELADI — bir xil taomlar, lekin TURLI taqdimotda. HTTP'da mijoz Accept sarlavhasi orqali "menga QAYSI formatda javob kerak" deb AYTADI (masalan application/json yoki text/plain), server esa BIR XIL ma'lumotni SO'RALGAN formatda qaytaradi — bu content negotiation (kontent kelishuvi) deb ataladi.

example.go
package main

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

type Book struct {
	ID     string  `json:"id"`
	Title  string  `json:"title"`
	Author string  `json:"author"`
	Price  float64 `json:"price"`
}

func main() {
	book := Book{ID: "1", Title: "Go bilan tanishuv", Author: "A. Karimov", Price: 45000}

	mux := http.NewServeMux()
	mux.HandleFunc("GET /books/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Accept") == "text/plain" {
			w.Header().Set("Content-Type", "text/plain")
			fmt.Fprintf(w, "%s — %s (%.0f so'm)", book.Title, book.Author, book.Price)
			return
		}
		w.Header().Set("Content-Type", "application/json")
		json.NewEncoder(w).Encode(book)
	})

	req1 := httptest.NewRequest("GET", "/books/1", nil)
	req1.Header.Set("Accept", "text/plain")
	rec1 := httptest.NewRecorder()
	mux.ServeHTTP(rec1, req1)
	fmt.Println(rec1.Body.String())

	req2 := httptest.NewRequest("GET", "/books/1", nil)
	req2.Header.Set("Accept", "application/json")
	rec2 := httptest.NewRecorder()
	mux.ServeHTTP(rec2, req2)
	fmt.Print(rec2.Body.String())
}

r.Header.Get("Accept") — mijoz "men QANDAY javob kutayapman" deb aytgan sarlavha. Handler BIR XIL book MA'LUMOTIDAN ikki TURLI taqdimot (JSON yoki oddiy matn) yaratadi — bu "Interface Design" darsidagi "ma'lumot va uning TAQDIMOTINI ajratish" g'oyasining HTTP darajasidagi ko'rinishi.

Bunday yondashuv AYNIQSA foydali: masalan brauzerlar odatda text/html yoki */* so'raydi, mobil ilovalar esa KO'PINCHA application/json — BIR XIL server, BIR XIL endpoint, lekin MIJOZGA MOS formatda javob beradi.

>_ Exercise

Standart holatni va QO'LLAB-QUVVATLANMAYDIGAN formatni ham to'g'ri boshqaring.

  • handlerni switch bilan yozing: "text/plain" -> matn, ""/"*/*"/"application/json" -> JSON, BOSHQA HAR QANDAY qiymat -> http.StatusNotAcceptable (406) va "qo'llab-quvvatlanmaydigan format" matni
  • Accept sarlavhasiz so'rov yuborib, STANDART holatda JSON qaytishini tekshiring
  • "application/xml" bilan so'rov yuborib, 406 qaytishini tekshiring

Stuck? Reveal a hint to help you.

Hints (0/3)

Key Takeaway

Key Takeaway:

Content negotiation — BIR XIL ma'lumotni Accept sarlavhasiga qarab TURLI formatda (JSON, matn) qaytaradi; qo'llab-quvvatlanmaydigan format so'ralganda esa, 406 status bilan buni ANIQ bildirish kerak.

NEXT UP

Testing Handlers: Table-Driven Tests

OUTPUT

$ go run main.go
Kodingizni ishga tushiring

Content Negotiation

Kontent kelishuvi (content negotiation)

Restoran ofitsianti mijozdan "qaysi tilda menyu kerak?" deb SO'RAYDI va shu tilda menyu OLIB KELADI — bir xil taomlar, lekin TURLI taqdimotda. HTTP'da mijoz Accept sarlavhasi orqali "menga QAYSI formatda javob kerak" deb AYTADI (masalan application/json yoki text/plain), server esa BIR XIL ma'lumotni SO'RALGAN formatda qaytaradi — bu content negotiation (kontent kelishuvi) deb ataladi.

example.go
package main

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

type Book struct {
	ID     string  `json:"id"`
	Title  string  `json:"title"`
	Author string  `json:"author"`
	Price  float64 `json:"price"`
}

func main() {
	book := Book{ID: "1", Title: "Go bilan tanishuv", Author: "A. Karimov", Price: 45000}

	mux := http.NewServeMux()
	mux.HandleFunc("GET /books/{id}", func(w http.ResponseWriter, r *http.Request) {
		if r.Header.Get("Accept") == "text/plain" {
			w.Header().Set("Content-Type", "text/plain")
			fmt.Fprintf(w, "%s — %s (%.0f so'm)", book.Title, book.Author, book.Price)
			return
		}
		w.Header().Set("Content-Type", "application/json")
		json.NewEncoder(w).Encode(book)
	})

	req1 := httptest.NewRequest("GET", "/books/1", nil)
	req1.Header.Set("Accept", "text/plain")
	rec1 := httptest.NewRecorder()
	mux.ServeHTTP(rec1, req1)
	fmt.Println(rec1.Body.String())

	req2 := httptest.NewRequest("GET", "/books/1", nil)
	req2.Header.Set("Accept", "application/json")
	rec2 := httptest.NewRecorder()
	mux.ServeHTTP(rec2, req2)
	fmt.Print(rec2.Body.String())
}

r.Header.Get("Accept") — mijoz "men QANDAY javob kutayapman" deb aytgan sarlavha. Handler BIR XIL book MA'LUMOTIDAN ikki TURLI taqdimot (JSON yoki oddiy matn) yaratadi — bu "Interface Design" darsidagi "ma'lumot va uning TAQDIMOTINI ajratish" g'oyasining HTTP darajasidagi ko'rinishi.

Bunday yondashuv AYNIQSA foydali: masalan brauzerlar odatda text/html yoki */* so'raydi, mobil ilovalar esa KO'PINCHA application/json — BIR XIL server, BIR XIL endpoint, lekin MIJOZGA MOS formatda javob beradi.

>_ Exercise

Standart holatni va QO'LLAB-QUVVATLANMAYDIGAN formatni ham to'g'ri boshqaring.

  • handlerni switch bilan yozing: "text/plain" -> matn, ""/"*/*"/"application/json" -> JSON, BOSHQA HAR QANDAY qiymat -> http.StatusNotAcceptable (406) va "qo'llab-quvvatlanmaydigan format" matni
  • Accept sarlavhasiz so'rov yuborib, STANDART holatda JSON qaytishini tekshiring
  • "application/xml" bilan so'rov yuborib, 406 qaytishini tekshiring

Stuck? Reveal a hint to help you.

Hints (0/3)

Key Takeaway

Key Takeaway:

Content negotiation — BIR XIL ma'lumotni Accept sarlavhasiga qarab TURLI formatda (JSON, matn) qaytaradi; qo'llab-quvvatlanmaydigan format so'ralganda esa, 406 status bilan buni ANIQ bildirish kerak.

NEXT UP

Testing Handlers: Table-Driven Tests