مرکزی مواد پر جائیں
ماڈیول 10 · سبق 5 از 5کورس میں 50/50~18 min
ماڈیول اسباق (5/5)

منی پروجیکٹ: ایک HTTP سرور

net/http stdlib پیکیج پروڈکشن کے لیے تیار HTTP سرور بنانے کے لیے کافی ہے: روٹنگ، ہینڈلرز، مڈل ویئر، شاندار شٹ ڈاؤن۔ کسی فریم ورک کی ضرورت نہیں ہے۔ عام REST APIs کے لیے یہ بنیاد ہے۔

ہیلو دنیا

Go
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"۔

ہینڈلر کے دستخط

تمام ہینڈلرز ایک ہی دستخط کا اشتراک کرتے ہیں:

Go
func(w http.ResponseWriter, r *http.Request)
  • w http.ResponseWriter — آؤٹ پٹ: ہیڈر، اسٹیٹس کوڈ، باڈی۔
  • r *http.Request — ان پٹ: طریقہ، URL، ہیڈر، باڈی، سیاق و سباق۔

عام پیٹرن:

Go
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 یہ طریقہ اور راستے کے پیرامیٹرز کے ساتھ پیٹرن کو سپورٹ کرتا ہے:

Go
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:

Go
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:

Go
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 موصول ہوتا ہے، تو آپ بند کرنے سے پہلے پرواز میں درخواستیں ختم کرنا چاہتے ہیں:

Go
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 باڈی پڑھنا

Go
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 آبجیکٹ کو نہیں پڑھتا (ان پٹ کی توثیق کے لیے مفید)۔

مشقیں

ورزش#go.m10.l5.e1
کوششیں: 0لوڈ ہو رہا ہے…

رجسٹرا l'handler hello sulla route '/' usando http.HandleFunc.

ایڈیٹر لوڈ ہو رہا ہے…

3 کوششوں کے بعد حل دستیاب ہے۔

ورزش#go.m10.l5.e2
کوششیں: 0لوڈ ہو رہا ہے…

Avvia il server su :8080 con http.ListenAndServe e stampa l'errore se non è nil.

ایڈیٹر لوڈ ہو رہا ہے…

3 کوششوں کے بعد حل دستیاب ہے۔

Quiz#go.m10.l5.e3
تیار

Qual è la firma idiomatica di un handler HTTP گو میں؟

Go
func H(???) { ... }
جواب کے اختیارات