मॉड्यूल पाठ (5/5)
मिनी-प्रोजेक्ट: एक HTTP सर्वर
net/http stdlib पैकेज उत्पादन के लिए तैयार HTTP सर्वर बनाने के लिए पर्याप्त है: रूटिंग, हैंडलर, मिडलवेयर, ग्रेसफुल शटडाउन। किसी रूपरेखा की आवश्यकता नहीं है. विशिष्ट REST API के लिए यह आधार है।
हैलो वर्ल्ड
package main
import (
"fmt"
"net/http"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello %s", r.URL.Path[1:])
})
if err := http.ListenAndServe(":8080", nil); err != nil {
panic(err)
}
}http.ListenAndServe ब्लॉक करता है और केवल त्रुटि पर वापस आता है। दूसरे तर्क के रूप में nil = "DefaultServeMux का उपयोग करें"।
हैंडलर के हस्ताक्षर
सभी संचालकों के हस्ताक्षर समान हैं:
func(w http.ResponseWriter, r *http.Request)w http.ResponseWriter— आउटपुट: हेडर, स्टेटस कोड, बॉडी।r *http.Request— इनपुट: विधि, यूआरएल, हेडर, बॉडी, संदर्भ।
विशिष्ट पैटर्न:
func ping(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK) // optional, defaults to 200
fmt.Fprintln(w, `{"ok":true}`)
}ServeMux के साथ रूटिंग
*http.ServeMux बेस राउटर है। चूँकि गो 1.22 यह विधि और पथ मापदंडों के साथ पैटर्न का समर्थन करता है:
mux := http.NewServeMux()
mux.HandleFunc("GET /users/{id}", func(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
fmt.Fprintln(w, "user", id)
})
mux.HandleFunc("POST /users", createUser)
http.ListenAndServe(":8080", mux)अधिक परिष्कृत राउटर्स (समूह, एकीकृत मिडलवेयर, रेगेक्स) के लिए chi, gorilla/mux, gin, echo हैं। stdlib 90% मामलों को कवर करता है।
डेकोरेटर के रूप में मिडलवेयर
मिडलवेयर एक फ़ंक्शन func(http.Handler) http.Handler है:
func logMW(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
log.Printf("%s %s %s", r.Method, r.URL.Path, time.Since(start))
})
}
http.ListenAndServe(":8080", logMW(mux))उन्हें श्रृंखलाबद्ध करने के लिए: logMW(authMW(rateLimitMW(mux))). प्रत्येक मिडलवेयर अगले को सजाता है।
ठीक नियंत्रण के लिए http.Server
http.ListenAndServe(addr, h) एक शॉर्टकट है। टाइमआउट, टीएलएस और ग्रेसफुल शटडाउन के लिए आपको http.Server को तुरंत चालू करना होगा:
srv := &http.Server{
Addr: ":8080",
Handler: mux,
ReadHeaderTimeout: 5 * time.Second,
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 2 * time.Minute,
}
log.Fatal(srv.ListenAndServe())सन्दर्भ सहित सुन्दर समापन
जब प्रक्रिया को SIGINT/SIGTERM प्राप्त होता है, तो आप बंद होने से पहले इन-फ़्लाइट अनुरोधों को पूरा करना चाहते हैं:
ctx, stop := signal.NotifyContext(context.Background(),
os.Interrupt, syscall.SIGTERM)
defer stop()
srv := &http.Server{Addr: ":8080", Handler: mux}
go func() {
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatal(err)
}
}()
<-ctx.Done() // wait for the signal
shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := srv.Shutdown(shutdownCtx); err != nil {
log.Println("shutdown:", err)
}srv.Shutdown नए कनेक्शन स्वीकार करना बंद कर देता है और सक्रिय कनेक्शन समाप्त होने की प्रतीक्षा करता है (समय सीमा बीतने तक)।
JSON बॉडी को पढ़ना
type CreateUserReq struct {
Name string `json:"name"`
}
func createUser(w http.ResponseWriter, r *http.Request) {
var req CreateUserReq
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// ... use req.Name
w.WriteHeader(http.StatusCreated)
}r.Body एक io.ReadCloser है: सर्वर इसे स्वचालित रूप से बंद कर देता है, लेकिन json.NewDecoder पहले JSON ऑब्जेक्ट (इनपुट को मान्य करने के लिए उपयोगी) को नहीं पढ़ता है।
अभ्यास
रजिस्टर करें हैंडलर हेलो रूट '/' http.HandleFunc का उपयोग करें।
3 प्रयासों के बाद समाधान उपलब्ध है
http.ListenAndServe पर सर्वर का उपयोग :8080 और त्रुटि शून्य है।
3 प्रयासों के बाद समाधान उपलब्ध है
गो में HTTP हैंडलर का क्या मतलब है?
func H(???) { ... }