মডিউল পাঠ (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_ — ইনপুট: পদ্ধতি, URL, শিরোনাম, বডি, প্রসঙ্গ।
সাধারণ প্যাটার্ন:
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 হল বেস রাউটার। যেহেতু Go 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) একটি শর্টকাট। টাইমআউট, TLS, এবং সুন্দর শাটডাউনের জন্য আপনাকে 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 প্রচেষ্টার পরে উপলব্ধ
Avvia il server su :8080 con http.ListenAndServe e stamp l'errore se non è nil.
সমাধান 3 প্রচেষ্টার পরে উপলব্ধ
কোয়াল è la firma idiomatica di un হ্যান্ডলার HTTP Go in?
func H(???) { ... }