Go net/http Server: Handlers, Routing & Middleware | Tutorial #32
Video: Go net/http Server: Handlers, Routing & Middleware | Tutorial #32 by Taught by Celeste AI - AI Coding Coach
Watch full page →Building HTTP Servers in Go: Handlers, Routing & Middleware
Go's standard library net/http package provides powerful tools to create web servers without external frameworks. In this tutorial, you'll learn how to register handlers, route requests with ServeMux, implement middleware for logging and authentication, and build a JSON REST API with proper request parsing and response encoding.
Code
package main
import (
"encoding/json"
"log"
"net/http"
"time"
"fmt"
)
// User represents a simple user model
type User struct {
ID string `json:"id"`
Name string `json:"name"`
}
// In-memory user storage
var users = map[string]User{}
// Logging middleware logs request method, path, and duration
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
duration := time.Since(start)
log.Printf("%s %s took %v", r.Method, r.URL.Path, duration)
})
}
// Auth middleware checks for X-API-Key header
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
apiKey := r.Header.Get("X-API-Key")
if apiKey != "secret123" {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}
// Handler for GET /users - returns all users as JSON
func getUsersHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(users)
}
// Handler for POST /users - creates a new user from JSON body
func createUserHandler(w http.ResponseWriter, r *http.Request) {
var user User
if err := json.NewDecoder(r.Body).Decode(&user); err != nil {
http.Error(w, "Bad Request", http.StatusBadRequest)
return
}
users[user.ID] = user
w.WriteHeader(http.StatusCreated)
json.NewEncoder(w).Encode(user)
}
func main() {
mux := http.NewServeMux()
// Register handlers with method patterns (Go 1.22+)
mux.HandleFunc("GET /users", getUsersHandler)
mux.HandleFunc("POST /users", createUserHandler)
// Wrap mux with middleware
handler := loggingMiddleware(authMiddleware(mux))
fmt.Println("Server listening on :8080")
http.ListenAndServe(":8080", handler)
}
Key Points
- Use http.HandleFunc or ServeMux.HandleFunc with method patterns like "GET /users" to route requests.
- Middleware functions wrap http.Handler to add cross-cutting concerns like logging and authentication.
- Use http.ResponseWriter to write headers, status codes, and JSON responses with json.NewEncoder.
- Parse JSON request bodies safely with json.NewDecoder and handle errors properly.
- Start the server with http.ListenAndServe, passing the final handler chain including middleware.