middleware

package
v1.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 5, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package middleware contains common middleware functions for use in web applications

Example

Example demonstrates a realistic JSON API middleware stack.

package main

import (
	"fmt"
	"log/slog"
	"net/http"
	"os"

	"github.com/harrydayexe/GoWebUtilities/middleware"
)

func main() {
	// Create a logger for production use
	logger := slog.New(slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{
		Level: slog.LevelInfo,
	}))

	// Create a typical middleware stack for JSON APIs
	// Order: logging (first) -> size limiting -> content-type (last)
	apiStack := middleware.CreateStack(
		middleware.NewLoggingMiddleware(logger),
		middleware.NewMaxBytesReader(10*1024*1024), // 10MB limit
		middleware.NewSetContentTypeJSON(),
	)

	// Create a mux and add API endpoints
	mux := http.NewServeMux()

	// User endpoint
	getUserHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Write([]byte(`{"id":1,"name":"Alice"}`))
	})

	// Apply middleware to all API routes
	mux.Handle("/api/users/", apiStack(getUserHandler))

	fmt.Println("JSON API server configured with logging, size limiting, and content-type middleware")
}
Output:
JSON API server configured with logging, size limiting, and content-type middleware

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Middleware

type Middleware func(h http.Handler) http.Handler

middleware is a function that wraps http.Handlers proving functionality before and after execution of the h handler.

func CreateStack

func CreateStack(xs ...Middleware) Middleware

CreateStack composes multiple middleware into a single middleware. Middleware are applied in the order provided: the first middleware in the list will be the outermost wrapper (executed first on the request).

Example

ExampleCreateStack demonstrates composing multiple middleware.

package main

import (
	"fmt"
	"log"
	"net/http"
	"net/http/httptest"

	"github.com/harrydayexe/GoWebUtilities/middleware"
)

func main() {
	// Create a middleware stack with multiple middleware
	stack := middleware.CreateStack(
		middleware.NewSetContentTypeJSON(),
		middleware.NewMaxBytesReader(1024),
	)

	// Create a base handler
	baseHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Write([]byte(`{"message":"hello"}`))
	})

	// Apply the stack to the handler
	wrappedHandler := stack(baseHandler)

	// Create a test server
	server := httptest.NewServer(wrappedHandler)
	defer server.Close()

	// Make a request
	resp, err := http.Get(server.URL)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	fmt.Printf("Content-Type: %s\n", resp.Header.Get("Content-Type"))
}
Output:
Content-Type: application/json
Example (Complete)

ExampleCreateStack_complete demonstrates a complete HTTP server setup with middleware.

package main

import (
	"fmt"
	"io"
	"log"
	"log/slog"
	"net/http"
	"net/http/httptest"

	"github.com/harrydayexe/GoWebUtilities/middleware"
)

func main() {
	// Create a logger (discarding output for this example)
	logger := slog.New(slog.NewJSONHandler(io.Discard, nil))

	// Create a complete middleware stack
	stack := middleware.CreateStack(
		middleware.NewLoggingMiddleware(logger),
		middleware.NewSetContentTypeJSON(),
		middleware.NewMaxBytesReader(1024),
	)

	// Create a mux and add handlers
	mux := http.NewServeMux()

	apiHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Write([]byte(`{"message":"hello"}`))
	})

	// Apply middleware to the handler
	mux.Handle("/api/", stack(apiHandler))

	// Create a test server
	server := httptest.NewServer(mux)
	defer server.Close()

	// Make a request
	resp, err := http.Get(server.URL + "/api/test")
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	fmt.Printf("Status: %d\n", resp.StatusCode)
	fmt.Printf("Content-Type: %s\n", resp.Header.Get("Content-Type"))
}
Output:
Status: 200
Content-Type: application/json

func NewLoggingMiddleware

func NewLoggingMiddleware(logger *slog.Logger) Middleware

NewLoggingMiddleware returns middleware that logs HTTP requests. Logs include method, path, status code, and duration.

Example

ExampleNewLoggingMiddleware demonstrates structured logging with middleware.

package main

import (
	"fmt"
	"io"
	"log"
	"log/slog"
	"net/http"
	"net/http/httptest"

	"github.com/harrydayexe/GoWebUtilities/middleware"
)

func main() {
	// Create a structured logger (logs to stderr in production)
	logger := slog.New(slog.NewTextHandler(io.Discard, nil))

	// Create logging middleware
	loggingMw := middleware.NewLoggingMiddleware(logger)

	// Create a simple handler
	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Write([]byte("success"))
	})

	// Apply the middleware
	wrappedHandler := loggingMw(handler)

	// Create a test server
	server := httptest.NewServer(wrappedHandler)
	defer server.Close()

	// Make a request (logging happens automatically)
	resp, err := http.Get(server.URL + "/api/test")
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	fmt.Printf("Request logged with status: %d\n", resp.StatusCode)
}
Output:
Request logged with status: 200

func NewMaxBytesReader

func NewMaxBytesReader(maxBytes int64) Middleware

NewMaxBytesReader returns middleware that limits request body size to maxBytes. Bodies exceeding this limit will cause an error response. This prevents resource exhaustion from overly large requests. If maxBytes is 0, defaults to 1MB

Example

ExampleNewMaxBytesReader demonstrates limiting request body size.

package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/httptest"
	"strings"

	"github.com/harrydayexe/GoWebUtilities/middleware"
)

func main() {
	// Create middleware that limits request body to 512 bytes
	limitMiddleware := middleware.NewMaxBytesReader(512)

	// Create a handler that reads the request body
	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		body, err := io.ReadAll(r.Body)
		if err != nil {
			http.Error(w, "Request body too large", http.StatusRequestEntityTooLarge)
			return
		}
		fmt.Fprintf(w, "Received %d bytes", len(body))
	})

	// Apply the middleware
	wrappedHandler := limitMiddleware(handler)

	// Create a test server
	server := httptest.NewServer(wrappedHandler)
	defer server.Close()

	// Test with small payload (should succeed)
	smallPayload := strings.NewReader("small data")
	resp, err := http.Post(server.URL, "text/plain", smallPayload)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()
	body, _ := io.ReadAll(resp.Body)

	fmt.Printf("Status: %d\n", resp.StatusCode)
	fmt.Printf("Response: %s\n", body)
}
Output:
Status: 200
Response: Received 10 bytes

func NewSetContentType

func NewSetContentType(contentType string) Middleware

NewSetContentType returns middleware that sets the Content-Type header for all responses. Common values: "application/json", "text/html; charset=utf-8".

func NewSetContentTypeJSON

func NewSetContentTypeJSON() Middleware

NewSetContentTypeJSON returns middleware that sets the Content-Type header to application/json. This is a convenience wrapper around NewSetContentType for JSON APIs. Apply this to route groups where all endpoints return JSON to avoid repetitive header setting in individual handlers.

Example

ExampleNewSetContentTypeJSON demonstrates creating and using the JSON content-type middleware.

package main

import (
	"fmt"
	"log"
	"net/http"
	"net/http/httptest"

	"github.com/harrydayexe/GoWebUtilities/middleware"
)

func main() {
	// Create a JSON content-type middleware
	jsonMiddleware := middleware.NewSetContentTypeJSON()

	// Create a simple handler that returns JSON data
	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusOK)
		w.Write([]byte(`{"status":"ok"}`))
	})

	// Apply the middleware to the handler
	wrappedHandler := jsonMiddleware(handler)

	// Create a test server
	server := httptest.NewServer(wrappedHandler)
	defer server.Close()

	// Make a request
	resp, err := http.Get(server.URL)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	fmt.Printf("Content-Type: %s\n", resp.Header.Get("Content-Type"))
}
Output:
Content-Type: application/json

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL