Goku

برنامه‌نویسی شبکه و HTTP در زبان Go

این جزوه به بررسی جامع برنامه‌نویسی شبکه و پروتکل HTTP در Go می‌پردازد. Go به دلیل کتابخانه استاندارد قدرتمند (net/http) و سادگی در مدیریت همزمانی، برای ساخت سرورهای وب و برنامه‌های شبکه‌ای بسیار مناسب است. تمام موضوعات درخواستی با جزئیات کامل و مثال‌های عملی شرح داده شده‌اند.


1. سرور HTTP پایه

1.1. مفهوم

پکیج net/http ابزارهای لازم برای ساخت سرورهای HTTP را فراهم می‌کند. یک سرور HTTP درخواست‌ها را دریافت کرده، پردازش می‌کند و پاسخ مناسب را ارسال می‌کند.

1.2. استفاده از net/http

ایجاد سرور ساده

package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World!")
}

func main() {
    http.HandleFunc("/", handler)
    fmt.Println("Server running on :8080")
    http.ListenAndServe(":8080", nil)
}

1.3. هندلرها

هندلرها توابعی هستند که درخواست‌های HTTP را پردازش می‌کنند. دو نوع اصلی:

1.4. پاسخ به درخواست‌ها

1.5. نکات پیشرفته

1.6. خطاهای رایج


2. مدیریت درخواست‌ها

2.1. مفهوم

مدیریت درخواست‌ها شامل استخراج اطلاعات از درخواست (مثل Query Parameters، Form Data، و Method‌ها) و پاسخ مناسب است.

2.2. کار با Query Parameters

Query Parameters در URL (مثل ?name=Ali) قرار دارند.

func handler(w http.ResponseWriter, r *http.Request) {
    name := r.URL.Query().Get("name")
    if name == "" {
        name = "Guest"
    }
    fmt.Fprintf(w, "Hello, %s!", name)
}

2.3. کار با Form Data

برای درخواست‌های POST یا PUT که داده‌های فرم دارند:

func handler(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodPost {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }
    r.ParseForm()
    username := r.Form.Get("username")
    fmt.Fprintf(w, "Welcome, %s!", username)
}

2.4. مدیریت Method‌ها

func handler(w http.ResponseWriter, r *http.Request) {
    switch r.Method {
    case http.MethodGet:
        fmt.Fprintf(w, "GET request received")
    case http.MethodPost:
        fmt.Fprintf(w, "POST request received")
    default:
        http.Error(w, "Method not supported", http.StatusMethodNotAllowed)
    }
}

2.5. نکات پیشرفته

2.6. خطاهای رایج


3. کار با JSON در HTTP

3.1. مفهوم

JSON فرمت رایج برای تبادل داده در برنامه‌های وب است. Go با پکیج encoding/json از آن پشتیبانی می‌کند.

3.2. ارسال داده‌های JSON

type User struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
}

func handler(w http.ResponseWriter, r *http.Request) {
    user := User{ID: 1, Name: "Ali"}
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(user)
}

3.3. دریافت داده‌های JSON

func handler(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodPost {
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
        return
    }
    var user User
    if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
        http.Error(w, "Invalid JSON", http.StatusBadRequest)
        return
    }
    fmt.Fprintf(w, "Received: %+v", user)
}

3.4. Middleware

Middleware توابعی هستند که قبل یا بعد از هندلر اجرا می‌شوند (مثل لاگ‌گیری، احراز هویت).

func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        next.ServeHTTP(w, r)
        fmt.Printf("%s %s %v\n", r.Method, r.URL.Path, time.Since(start))
    })
}

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello!")
    })
    http.ListenAndServe(":8080", loggingMiddleware(mux))
}

3.5. نکات پیشرفته

3.6. خطاهای رایج


4. فریم‌ورک‌های وب

4.1. مفهوم

فریم‌ورک‌های وب ابزارهایی هستند که توسعه برنامه‌های وب را ساده‌تر می‌کنند. سه فریم‌ورک محبوب در Go عبارتند از Gin، Echo، و Fiber.

4.2. Gin

نصب

go get -u github.com/gin-gonic/gin

مثال

package main

import "github.com/gin-gonic/gin"

func main() {
    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run(":8080")
}

4.3. Echo

نصب

go get -u github.com/labstack/echo/v4

مثال

package main

import (
    "net/http"
    "github.com/labstack/echo/v4"
)

func main() {
    e := echo.New()
    e.GET("/ping", func(c echo.Context) error {
        return c.JSON(http.StatusOK, map[string]string{"message": "pong"})
    })
    e.Start(":8080")
}

4.4. Fiber

نصب

go get -u github.com/gofiber/fiber/v2

مثال

package main

import "github.com/gofiber/fiber/v2"

func main() {
    app := fiber.New()
    app.Get("/ping", func(c *fiber.Ctx) error {
        return c.JSON(fiber.Map{"message": "pong"})
    })
    app.Listen(":8080")
}

4.5. نکات پیشرفته

4.6. خطاهای رایج


5. REST API

5.1. مفهوم

REST (Representational State Transfer) یک معماری برای طراحی API‌های وب است که از متدهای HTTP (GET، POST، PUT، DELETE) استفاده می‌کند.

5.2. طراحی REST API

5.3. پیاده‌سازی

package main

import (
    "encoding/json"
    "net/http"
    "strconv"
)

type User struct {
    ID   int    `json:"id"`
    Name string `json:"name"`
}

var users = map[int]User{
    1: {ID: 1, Name: "Ali"},
}

func main() {
    mux := http.NewServeMux()

    // دریافت همه کاربران
    mux.HandleFunc("GET /users", func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(users)
    })

    // دریافت کاربر خاص
    mux.HandleFunc("GET /users/", func(w http.ResponseWriter, r *http.Request) {
        idStr := r.URL.Path[len("/users/"):]
        id, _ := strconv.Atoi(idStr)
        user, ok := users[id]
        if !ok {
            http.Error(w, "User not found", http.StatusNotFound)
            return
        }
        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(user)
    })

    // ایجاد کاربر
    mux.HandleFunc("POST /users", func(w http.ResponseWriter, r *http.Request) {
        var user User
        if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
            http.Error(w, "Invalid input", http.StatusBadRequest)
            return
        }
        user.ID = len(users) + 1
        users[user.ID] = user
        w.Header().Set("Content-Type", "application/json")
        w.WriteHeader(http.StatusCreated)
        json.NewEncoder(w).Encode(user)
    })

    http.ListenAndServe(":8080", mux)
}

5.4. بهترین شیوه‌ها

5.5. نکات پیشرفته

5.6. خطاهای رایج


6. WebSocket

6.1. مفهوم

WebSocket پروتکلی برای ارتباط دوطرفه و بلادرنگ بین سرور و کلاینت است. پکیج github.com/gorilla/websocket ابزار محبوبی در Go است.

6.2. نصب

go get -u github.com/gorilla/websocket

6.3. پیاده‌سازی

package main

import (
    "log"
    "net/http"
    "github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
    CheckOrigin: func(r *http.Request) bool {
        return true // در تولید محدود کنید
    },
}

func handler(w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println(err)
        return
    }
    defer conn.Close()

    for {
        msgType, msg, err := conn.ReadMessage()
        if err != nil {
            log.Println(err)
            return
        }
        log.Printf("Received: %s", msg)
        err = conn.WriteMessage(msgType, msg)
        if err != nil {
            log.Println(err)
            return
        }
    }
}

func main() {
    http.HandleFunc("/ws", handler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}

6.4. نکات پیشرفته

6.5. خطاهای رایج


7. کلاینت HTTP

7.1. مفهوم

کلاینت HTTP برای ارسال درخواست‌ها به سرورهای دیگر استفاده می‌شود.

7.2. ارسال درخواست‌ها

GET

resp, err := http.Get("https://api.example.com/data")
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
fmt.Println(string(body))

POST

data := []byte(`{"name":"Ali"}`)
resp, err := http.Post("https://api.example.com/users", "application/json", bytes.NewBuffer(data))
if err != nil {
    log.Fatal(err)
}
defer resp.Body.Close()

7.3. کلاینت سفارشی

client := &http.Client{
    Timeout: 10 * time.Second,
}
req, err := http.NewRequest("GET", "https://api.example.com/data", nil)
if err != nil {
    log.Fatal(err)
}
req.Header.Set("Authorization", "Bearer token")
resp, err := client.Do(req)

7.4. نکات پیشرفته

7.5. خطاهای رایج


8. امنیت در HTTP

8.1. CORS

برای اجازه دسترسی از دامنه‌های دیگر:

func corsMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Access-Control-Allow-Origin", "*")
        w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE")
        w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
        if r.Method == http.MethodOptions {
            return
        }
        next.ServeHTTP(w, r)
    })
}

8.2. CSRF

برای جلوگیری از حملات CSRF:

8.3. TLS

برای فعال‌سازی HTTPS:

http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil)

8.4. نکات پیشرفته

8.5. خطاهای رایج


9. بهترین شیوه‌ها و نکات


10. نتیجه‌گیری

این جزوه تمام جنبه‌های برنامه‌نویسی شبکه و HTTP در Go را با جزئیات کامل پوشش داد. از ساخت سرورهای ساده تا پیاده‌سازی REST API، WebSocket، و امنیت، هر بخش با مثال‌های عملی و نکات پیشرفته ارائه شد. برای یادگیری عمیق‌تر: