Middleware
Muammo: har bir HTTP so’rovga bir xil ishlarni qo’shmoqchisiz - log, autentifikatsiya, tiklanish (recover) - lekin bu kodni har bir handler ichida takrorlamasdan. Bu Decorator patterni HTTP dunyosidagi ko’rinishi.
G’oya: middleware - func(http.Handler) http.Handler. U kelgan handler’ni o’rab, o’z ishini bajaradi va keyin ichkaridagini chaqiradi. Bir necha middleware’ni zanjir qilib ulasangiz, so’rov qatlamdan qatlamga o’tadi.
package main
import (
"fmt"
"net/http"
"net/http/httptest"
)
type Middleware func(http.Handler) http.Handler
func Logging(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Printf("LOG: %s %s\n", r.Method, r.URL.Path)
next.ServeHTTP(w, r)
})
}
func Auth(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("X-Token") != "secret" {
http.Error(w, "forbidden", http.StatusForbidden)
return
}
fmt.Println("AUTH: ruxsat berildi")
next.ServeHTTP(w, r)
})
}
// Chain middleware'larni ketma-ket bog'laydi (birinchisi eng tashqarida).
func Chain(h http.Handler, mws ...Middleware) http.Handler {
for i := len(mws) - 1; i >= 0; i-- {
h = mws[i](h)
}
return h
}
func main() {
final := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "salom, foydalanuvchi")
})
handler := Chain(final, Logging, Auth)
req := httptest.NewRequest(http.MethodGet, "/profile", nil)
req.Header.Set("X-Token", "secret")
rec := httptest.NewRecorder()
handler.ServeHTTP(rec, req)
fmt.Printf("status=%d body=%q\n", rec.Code, rec.Body.String())
}$ go run middleware.go
LOG: GET /profile
AUTH: ruxsat berildi
status=200 body="salom, foydalanuvchi\n"So’rov avval Logging, keyin Auth, so’ng handler tartibida o’tdi. Token noto’g’ri bo’lsa, Auth zanjirni to’xtatib, handler’ga umuman yetib bormaydi.
Qachon: har qanday HTTP xizmatida kesib o’tuvchi vazifalar (cross-cutting) uchun. Go note: bu Go veb-dasturlashning asosiy naqshi; chi, gin va standart net/http shu imzoga tayanadi.
Manba / batafsil: go.dev - net/http Handler