Documentation
¶
Overview ¶
Package httpserver extends the functionality of the standard library http.Server.
Key Features: ¶
- Manage routing paths, middleware registration, and handler registrations of the standard library http.Server.
- Some built-in middleware.
ServeMux ¶
ServeMux extends http.Handler designed to manage routing paths, middleware registration, and handler registrations of the standard library http.Server. It serves as a versatile routing mechanism that can handle middleware and nested routers efficiently.
Methods for adding middleware:
- ServeMux.Use: Appends one or more middlewares.
- ServeMux.With: Appends one or more middlewares and register the Handle inline.
Methods for managing the routing path:
- ServeMux.Group: Inline router manager, inheriting the middleware stack.
- ServeMux.Route: Subrouter manager, inheriting the middleware stack.
- ServeMux.Mount: Attaches external routers or handlers.
Methods for registering an http handler:
- ServeMux.Connect: Registers a handler for the HTTP CONNECT method.
- ServeMux.Delete: Registers a handler for the HTTP DELETE method.
- ServeMux.Get: Registers a handler for the HTTP GET method.
- ServeMux.Head: Registers a handler for the HTTP HEAD method.
- ServeMux.Options: Registers a handler for the HTTP OPTIONS method.
- ServeMux.Patch: Registers a handler for the HTTP PATCH method.
- ServeMux.Post: Registers a handler for the HTTP POST method.
- ServeMux.Put: Registers a handler for the HTTP PUT method.
- ServeMux.Trace: Registers a handler for the HTTP TRACE method.
- ServeMux.Method: Registers a handler for the custom HTTP method.
Middlewares ¶
- MiddlewareLogging: Logs each incoming request along with useful metadata regarding the request.
- MiddlewareRecover: Recovers from panics, logs the panic, and responds with an HTTP status of 500 (Internal Server Error).
- MiddlewareTelemetryTag: Adds attributes to spans and metrics for telemetry purposes.
Index ¶
- func MiddlewareLogging(next http.Handler) http.Handler
- func MiddlewareRecover(next http.Handler) http.Handler
- func MiddlewareTelemetryTag(next http.Handler) http.Handler
- type Handle
- type Router
- type ServeMux
- func (mux *ServeMux) Connect(pattern string, handlerFn http.HandlerFunc)
- func (mux *ServeMux) Delete(pattern string, handlerFn http.HandlerFunc)
- func (mux *ServeMux) Get(pattern string, handlerFn http.HandlerFunc)
- func (mux *ServeMux) Group(pattern string) Router
- func (mux *ServeMux) Head(pattern string, handlerFn http.HandlerFunc)
- func (mux *ServeMux) Method(method, pattern string, handlerFn http.HandlerFunc)
- func (mux *ServeMux) Mount(pattern string, handler http.Handler)
- func (mux *ServeMux) Options(pattern string, handlerFn http.HandlerFunc)
- func (mux *ServeMux) Patch(pattern string, handlerFn http.HandlerFunc)
- func (mux *ServeMux) Post(pattern string, handlerFn http.HandlerFunc)
- func (mux *ServeMux) Put(pattern string, handlerFn http.HandlerFunc)
- func (mux *ServeMux) Route(pattern string, fn func(sub Router))
- func (mux *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (mux *ServeMux) Trace(pattern string, handlerFn http.HandlerFunc)
- func (mux *ServeMux) Use(middlewares ...func(http.Handler) http.Handler)
- func (mux *ServeMux) With(middlewares ...func(http.Handler) http.Handler) Handle
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func MiddlewareLogging ¶ added in v0.0.6
MiddlewareLogging is a middleware that logs each incoming request along with useful metadata regarding the request.
Response Status Handling:
- Error: For response status < 100 and >= 500
- Warn: For response status < 200 and >= 400
- Info: Other response status
Log Identifier Handling:
- If the X-Logger-ID header is present in the request, its value will be used as the log identifier.
- If the header is not present or if the value is invalid, a new log identifier will be generated using UUID v7.
- The log identifier is then added to the context logger.ContextLogID.
Log Level Handling:
- If the X-Logger-Level header is present in the request, its value will be used as the minimum log level. Allowing lower priority logs at runtime.
- The minimum log level is then added to the context logger.ContextMinLevel.
Important Note:
- MiddlewareLogging should be positioned before any other middleware that may alter the response, such as MiddlewareRecover.
- Must be used with logger.NewHandler to register the log handle and allow lower priority logging at runtime.
Example:
mux := httpserver.NewServeMux()
mux.Use(httpserver.MiddlewareLogging) // <--<< MiddlewareLogging should come before MiddlewareRecover
mux.Use(httpserver.MiddlewareRecover)
mux.Get("/", handler)
Example ¶
package main
import (
"fmt"
"log"
"log/slog"
"net/http"
"github.com/telmoandrade/go-library/httpserver"
"github.com/telmoandrade/go-library/logger"
"go.opentelemetry.io/contrib/bridges/otelslog"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
)
func handlerHello(w http.ResponseWriter, r *http.Request) {
if _, err := w.Write([]byte("hello")); err != nil {
log.Printf("Write failed: %v\n", err)
}
}
func main() {
slog.SetDefault(logger.NewLogger(
logger.WithMinLevel(slog.LevelInfo),
logger.WithHandler(otelslog.NewHandler("")),
))
mux := httpserver.NewServeMux()
mux.Use(
httpserver.MiddlewareLogging,
httpserver.MiddlewareRecover,
otelhttp.NewMiddleware(""),
httpserver.MiddlewareTelemetryTag,
)
mux.Get("/hello", handlerHello)
s := &http.Server{
Addr: "0.0.0.0:8080",
Handler: mux,
}
fmt.Print(s != nil)
}
Output: true
func MiddlewareRecover ¶ added in v0.0.6
MiddlewareRecover is a middleware that recovers from panics, logs the panic, and responds with an HTTP status of 500 (Internal Server Error).
Example ¶
package main
import (
"fmt"
"log"
"log/slog"
"net/http"
"github.com/telmoandrade/go-library/httpserver"
"github.com/telmoandrade/go-library/logger"
"go.opentelemetry.io/contrib/bridges/otelslog"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
)
func handlerHello(w http.ResponseWriter, r *http.Request) {
if _, err := w.Write([]byte("hello")); err != nil {
log.Printf("Write failed: %v\n", err)
}
}
func main() {
slog.SetDefault(logger.NewLogger(
logger.WithMinLevel(slog.LevelInfo),
logger.WithHandler(otelslog.NewHandler("")),
))
mux := httpserver.NewServeMux()
mux.Use(
httpserver.MiddlewareLogging,
httpserver.MiddlewareRecover,
otelhttp.NewMiddleware(""),
httpserver.MiddlewareTelemetryTag,
)
mux.Get("/hello", handlerHello)
s := &http.Server{
Addr: "0.0.0.0:8080",
Handler: mux,
}
fmt.Print(s != nil)
}
Output: true
func MiddlewareTelemetryTag ¶ added in v0.0.6
MiddlewareTelemetryTag is a middleware that adds attributes to spans and metrics for telemetry purposes.
Adds telemetry attributes for monitoring:
- http.route: Indicates the route of the HTTP request used in spans and metrics.
- log.id: Log identifier associated with the request used in spans.
Example ¶
package main
import (
"fmt"
"log"
"log/slog"
"net/http"
"github.com/telmoandrade/go-library/httpserver"
"github.com/telmoandrade/go-library/logger"
"go.opentelemetry.io/contrib/bridges/otelslog"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
)
func handlerHello(w http.ResponseWriter, r *http.Request) {
if _, err := w.Write([]byte("hello")); err != nil {
log.Printf("Write failed: %v\n", err)
}
}
func main() {
slog.SetDefault(logger.NewLogger(
logger.WithMinLevel(slog.LevelInfo),
logger.WithHandler(otelslog.NewHandler("")),
))
mux := httpserver.NewServeMux()
mux.Use(
httpserver.MiddlewareLogging,
httpserver.MiddlewareRecover,
otelhttp.NewMiddleware(""),
httpserver.MiddlewareTelemetryTag,
)
mux.Get("/hello", handlerHello)
s := &http.Server{
Addr: "0.0.0.0:8080",
Handler: mux,
}
fmt.Print(s != nil)
}
Output: true
Types ¶
type Handle ¶
type Handle interface {
// Connect registers a handler for the HTTP CONNECT method, under the current routing path plus the specified pattern.
Connect(pattern string, handlerFn http.HandlerFunc)
// Delete registers a handler for the HTTP DELETE method, under the current routing path plus the specified pattern.
Delete(pattern string, handlerFn http.HandlerFunc)
// Get registers a handler for the HTTP GET method, under the current routing path plus the specified pattern.
Get(pattern string, handlerFn http.HandlerFunc)
// Head registers a handler for the HTTP HEAD method, under the current routing path plus the specified pattern.
Head(pattern string, handlerFn http.HandlerFunc)
// Options registers a handler for the HTTP OPTIONS method, under the current routing path plus the specified pattern.
Options(pattern string, handlerFn http.HandlerFunc)
// Patch registers a handler for the HTTP PATCH method, under the current routing path plus the specified pattern.
Patch(pattern string, handlerFn http.HandlerFunc)
// Post registers a handler for the HTTP POST method, under the current routing path plus the specified pattern.
Post(pattern string, handlerFn http.HandlerFunc)
// Put registers a handler for the HTTP PUT method, under the current routing path plus the specified pattern.
Put(pattern string, handlerFn http.HandlerFunc)
// Trace registers a handler for the HTTP TRACE method, under the current routing path plus the specified pattern.
Trace(pattern string, handlerFn http.HandlerFunc)
// Method registers a handler for the custom HTTP method, under the current routing path plus the specified pattern.
Method(method, pattern string, handlerFn http.HandlerFunc)
}
Handle interface allows the registration of HTTP handlers under the current routing path plus the specified pattern. It includes methods for each standard HTTP method.
type Router ¶
type Router interface {
Handle
// Use appends one or more middlewares to the middleware stack for the Router in the current routing path.
Use(middlewares ...func(http.Handler) http.Handler)
// With appends one or more middlewares to the middleware stack in the current routing path to register the inline Handle.
With(middlewares ...func(http.Handler) http.Handler) Handle
// Group return a new inline Router under the current routing path plus the specified pattern, inheriting the middleware stack.
Group(pattern string) Router
// Route allowing additional routes to be defined within the subrouter under the current routing path plus the specified pattern, inheriting the middleware stack.
Route(pattern string, fn func(sub Router))
// Mount attaches another http.Handler under the current routing path plus the specified pattern, useful for integrating external routers or handlers.
Mount(pattern string, h http.Handler)
}
Router interface extends the Handle interface. It is designed to manage routing paths, middleware registration, and handler registrations.
type ServeMux ¶
type ServeMux struct {
// contains filtered or unexported fields
}
ServeMux extends http.Handler designed to manage routing paths, middleware registration, and handler registrations of the standard library http.Server. It serves as a versatile routing mechanism that can handle middleware and nested routers efficiently.
Behavior:
- The ServeMux stores the routing path to register middlewares and handlers.
- If a pattern using the host conflicts with one that is already registered, it will cause a panic.
func NewServeMux ¶
func NewServeMux() *ServeMux
NewServeMux creates and returns a new instance of ServeMux with enhanced routing and middleware capabilities.
Example ¶
package main
import (
"fmt"
"log"
"net/http"
"github.com/telmoandrade/go-library/httpserver"
)
func handlerHello(w http.ResponseWriter, r *http.Request) {
if _, err := w.Write([]byte("hello")); err != nil {
log.Printf("Write failed: %v\n", err)
}
}
func main() {
mux := httpserver.NewServeMux()
mux.Get("/hello", handlerHello)
s := &http.Server{
Addr: "0.0.0.0:8080",
Handler: mux,
}
fmt.Print(s != nil)
}
Output: true
func (*ServeMux) Connect ¶
func (mux *ServeMux) Connect(pattern string, handlerFn http.HandlerFunc)
Connect registers a handler for the HTTP CONNECT method, under the current routing path plus the specified pattern.
Example ¶
package main
import (
"net/http"
"github.com/telmoandrade/go-library/httpserver"
)
func handler(w http.ResponseWriter, r *http.Request) {}
func main() {
mux := httpserver.NewServeMux()
mux.Connect("/pattern", handler)
}
func (*ServeMux) Delete ¶
func (mux *ServeMux) Delete(pattern string, handlerFn http.HandlerFunc)
Delete registers a handler for the HTTP DELETE method, under the current routing path plus the specified pattern.
Example ¶
package main
import (
"net/http"
"github.com/telmoandrade/go-library/httpserver"
)
func handler(w http.ResponseWriter, r *http.Request) {}
func main() {
mux := httpserver.NewServeMux()
mux.Delete("/pattern", handler)
}
func (*ServeMux) Get ¶
func (mux *ServeMux) Get(pattern string, handlerFn http.HandlerFunc)
Get registers a handler for the HTTP GET method, under the current routing path plus the specified pattern.
Example ¶
package main
import (
"net/http"
"github.com/telmoandrade/go-library/httpserver"
)
func handler(w http.ResponseWriter, r *http.Request) {}
func main() {
mux := httpserver.NewServeMux()
mux.Get("/pattern", handler)
}
func (*ServeMux) Group ¶
Group return a new inline Router under the current routing path plus the specified pattern, inheriting the middleware stack.
Example ¶
package main
import (
"context"
"fmt"
"net/http"
"github.com/telmoandrade/go-library/httpserver"
)
type ctxKey struct {
name string
}
func middlewarePathValue(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
ctx := context.WithValue(r.Context(), ctxKey{"id"}, id)
req := r.WithContext(ctx)
next.ServeHTTP(w, req)
})
}
func handlerGetUser(w http.ResponseWriter, r *http.Request) {
id := r.Context().Value(ctxKey{"id"}).(string)
fmt.Println(id)
}
func handlerPutUser(w http.ResponseWriter, r *http.Request) {
id := r.Context().Value(ctxKey{"id"}).(string)
fmt.Println(id)
}
func main() {
mux := httpserver.NewServeMux()
muxUser := mux.Group("/user")
muxUser.Use(middlewarePathValue)
muxUser.Get("/{id}", handlerGetUser)
muxUser.Put("/{id}", handlerPutUser)
s := &http.Server{
Addr: "0.0.0.0:8080",
Handler: mux,
}
fmt.Print(s != nil)
}
Output: true
func (*ServeMux) Head ¶
func (mux *ServeMux) Head(pattern string, handlerFn http.HandlerFunc)
Head registers a handler for the HTTP HEAD method, under the current routing path plus the specified pattern.
Example ¶
package main
import (
"net/http"
"github.com/telmoandrade/go-library/httpserver"
)
func handler(w http.ResponseWriter, r *http.Request) {}
func main() {
mux := httpserver.NewServeMux()
mux.Head("/pattern", handler)
}
func (*ServeMux) Method ¶
func (mux *ServeMux) Method(method, pattern string, handlerFn http.HandlerFunc)
Method registers a handler for the custom HTTP method, under the current routing path plus the specified pattern.
Example ¶
package main
import (
"net/http"
"github.com/telmoandrade/go-library/httpserver"
)
func handler(w http.ResponseWriter, r *http.Request) {}
func main() {
mux := httpserver.NewServeMux()
mux.Method("CUSTOM", "/pattern", handler)
}
func (*ServeMux) Mount ¶
Mount attaches another http.Handler under the current routing path plus the specified pattern, useful for integrating external routers or handlers.
Important Note:
- Avoid using this method to attach another multiplexer as it does not inherit the middleware stack.
- It is slower to resolve the multiplexer for HTTP requests compared to using the built-in routing methods.
Example ¶
package main
import (
"context"
"fmt"
"net/http"
"github.com/telmoandrade/go-library/httpserver"
)
type ctxKey struct {
name string
}
func middlewarePathValue(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
ctx := context.WithValue(r.Context(), ctxKey{"id"}, id)
req := r.WithContext(ctx)
next.ServeHTTP(w, req)
})
}
func handlerGetUser(w http.ResponseWriter, r *http.Request) {
id := r.Context().Value(ctxKey{"id"}).(string)
fmt.Println(id)
}
func handlerPutUser(w http.ResponseWriter, r *http.Request) {
id := r.Context().Value(ctxKey{"id"}).(string)
fmt.Println(id)
}
func main() {
muxUser := httpserver.NewServeMux()
muxUser.Use(middlewarePathValue)
muxUser.Get("/{id}", handlerGetUser)
muxUser.Put("/{id}", handlerPutUser)
mux := httpserver.NewServeMux()
mux.Mount("/user", muxUser)
s := &http.Server{
Addr: "0.0.0.0:8080",
Handler: mux,
}
fmt.Print(s != nil)
}
Output: true
func (*ServeMux) Options ¶
func (mux *ServeMux) Options(pattern string, handlerFn http.HandlerFunc)
Options registers a handler for the HTTP OPTIONS method, under the current routing path plus the specified pattern.
Example ¶
package main
import (
"net/http"
"github.com/telmoandrade/go-library/httpserver"
)
func handler(w http.ResponseWriter, r *http.Request) {}
func main() {
mux := httpserver.NewServeMux()
mux.Options("/pattern", handler)
}
func (*ServeMux) Patch ¶
func (mux *ServeMux) Patch(pattern string, handlerFn http.HandlerFunc)
Patch registers a handler for the HTTP PATCH method, under the current routing path plus the specified pattern.
Example ¶
package main
import (
"net/http"
"github.com/telmoandrade/go-library/httpserver"
)
func handler(w http.ResponseWriter, r *http.Request) {}
func main() {
mux := httpserver.NewServeMux()
mux.Patch("/pattern", handler)
}
func (*ServeMux) Post ¶
func (mux *ServeMux) Post(pattern string, handlerFn http.HandlerFunc)
Post registers a handler for the HTTP POST method, under the current routing path plus the specified pattern.
Example ¶
package main
import (
"net/http"
"github.com/telmoandrade/go-library/httpserver"
)
func handler(w http.ResponseWriter, r *http.Request) {}
func main() {
mux := httpserver.NewServeMux()
mux.Post("/pattern", handler)
}
func (*ServeMux) Put ¶
func (mux *ServeMux) Put(pattern string, handlerFn http.HandlerFunc)
Put registers a handler for the HTTP PUT method, under the current routing path plus the specified pattern.
Example ¶
package main
import (
"net/http"
"github.com/telmoandrade/go-library/httpserver"
)
func handler(w http.ResponseWriter, r *http.Request) {}
func main() {
mux := httpserver.NewServeMux()
mux.Put("/pattern", handler)
}
func (*ServeMux) Route ¶
Route allowing additional routes to be defined within the sub-Router under the current routing path plus the specified pattern, inheriting the middleware stack.
Example ¶
package main
import (
"context"
"fmt"
"net/http"
"github.com/telmoandrade/go-library/httpserver"
)
type ctxKey struct {
name string
}
func middlewarePathValue(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
ctx := context.WithValue(r.Context(), ctxKey{"id"}, id)
req := r.WithContext(ctx)
next.ServeHTTP(w, req)
})
}
func handlerGetUser(w http.ResponseWriter, r *http.Request) {
id := r.Context().Value(ctxKey{"id"}).(string)
fmt.Println(id)
}
func handlerPutUser(w http.ResponseWriter, r *http.Request) {
id := r.Context().Value(ctxKey{"id"}).(string)
fmt.Println(id)
}
func main() {
mux := httpserver.NewServeMux()
mux.Route("/user", func(muxUser httpserver.Router) {
muxUser.Use(middlewarePathValue)
muxUser.Get("/{id}", handlerGetUser)
muxUser.Put("/{id}", handlerPutUser)
})
s := &http.Server{
Addr: "0.0.0.0:8080",
Handler: mux,
}
fmt.Print(s != nil)
}
Output: true
func (*ServeMux) ServeHTTP ¶ added in v0.0.6
func (mux *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP dispatches the request to the handler whose pattern most closely matches the request URL.
func (*ServeMux) Trace ¶
func (mux *ServeMux) Trace(pattern string, handlerFn http.HandlerFunc)
Trace registers a handler for the HTTP TRACE method, under the current routing path plus the specified pattern.
Example ¶
package main
import (
"net/http"
"github.com/telmoandrade/go-library/httpserver"
)
func handler(w http.ResponseWriter, r *http.Request) {}
func main() {
mux := httpserver.NewServeMux()
mux.Trace("/pattern", handler)
}
func (*ServeMux) Use ¶
Use appends one or more middlewares to the middleware stack for the Router in the current routing path.
Example ¶
package main
import (
"context"
"fmt"
"net/http"
"github.com/telmoandrade/go-library/httpserver"
)
type ctxKey struct {
name string
}
func middlewarePathValue(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
ctx := context.WithValue(r.Context(), ctxKey{"id"}, id)
req := r.WithContext(ctx)
next.ServeHTTP(w, req)
})
}
func handlerGetUser(w http.ResponseWriter, r *http.Request) {
id := r.Context().Value(ctxKey{"id"}).(string)
fmt.Println(id)
}
func handlerPutUser(w http.ResponseWriter, r *http.Request) {
id := r.Context().Value(ctxKey{"id"}).(string)
fmt.Println(id)
}
func main() {
mux := httpserver.NewServeMux()
mux.Use(middlewarePathValue)
mux.Get("/user/{id}", handlerGetUser)
mux.Put("/user/{id}", handlerPutUser)
}
func (*ServeMux) With ¶
With appends one or more middlewares to the middleware stack in the current routing path to register the inline Handle.
Example ¶
package main
import (
"context"
"fmt"
"net/http"
"github.com/telmoandrade/go-library/httpserver"
)
type ctxKey struct {
name string
}
func middlewarePathValue(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
ctx := context.WithValue(r.Context(), ctxKey{"id"}, id)
req := r.WithContext(ctx)
next.ServeHTTP(w, req)
})
}
func handlerGetUser(w http.ResponseWriter, r *http.Request) {
id := r.Context().Value(ctxKey{"id"}).(string)
fmt.Println(id)
}
func main() {
mux := httpserver.NewServeMux()
mux.With(middlewarePathValue).Get("/user/{id}", handlerGetUser)
}