all repos — homestead @ b16c1c7338333ad5f9c968f7fa579015d350672a

Code for my website

extract HTTP logic to shared module

Alan Pearce
commit

b16c1c7338333ad5f9c968f7fa579015d350672a

parent

1ac299018401dc48caeb862b4dcc117a7a65e091

1 file changed, 74 insertions(+), 0 deletions(-)

changed files
A shared/http/mux.go
@@ -0,0 +1,74 @@
+package http + +import ( + "net/http" + + "alin.ovh/x/log" +) + +// HandleFunc is a function that handles an HTTP request and may return an Error. +type HandleFunc func(http.ResponseWriter, *http.Request) *Error + +// Handler is an interface for types that can serve HTTP requests and may return an Error. +type Handler interface { + ServeHTTP(http.ResponseWriter, *http.Request) *Error +} + +// ErrorHandler is a function that handles HTTP errors. +type ErrorHandler func(*Error, http.ResponseWriter, *http.Request) + +// ServeMux is an HTTP request multiplexer with error handling support. +// It matches the URL of each incoming request against a list of registered +// patterns and calls the handler for the pattern that most closely matches the URL. +type ServeMux struct { + log *log.Logger + errorHandler ErrorHandler + *http.ServeMux +} + +// NewServeMux creates a new ServeMux with a default error handler. +func NewServeMux() *ServeMux { + return &ServeMux{ + ServeMux: http.NewServeMux(), + errorHandler: func(err *Error, w http.ResponseWriter, _ *http.Request) { + http.Error(w, err.Message, err.Code) + }, + } +} + +// WithLogger sets the logger for this ServeMux and returns the ServeMux. +func (sm *ServeMux) WithLogger(logger *log.Logger) *ServeMux { + sm.log = logger + + return sm +} + +// Handle registers the handler for the given pattern. +// If the handler returns an error, the ServeMux's error handler will be invoked. +func (sm *ServeMux) Handle(pattern string, handler Handler) { + sm.HandleFunc(pattern, handler.ServeHTTP) +} + +// HandleFunc registers the handler function for the given pattern. +// If the handler returns an error, the ServeMux's error handler will be invoked. +func (sm *ServeMux) HandleFunc(pattern string, handler HandleFunc) { + sm.ServeMux.HandleFunc(pattern, func(w http.ResponseWriter, r *http.Request) { + defer func() { + if fail := recover(); fail != nil { + w.WriteHeader(http.StatusInternalServerError) + if sm.log != nil { + sm.log.Error("runtime panic!", "error", fail) + } + } + }() + if err := handler(w, r); err != nil { + sm.errorHandler(err, w, r) + } + }) +} + +// HandleError sets the error handler for this ServeMux. +// The error handler is called whenever a handler returns a non-nil error. +func (sm *ServeMux) HandleError(fn ErrorHandler) { + sm.errorHandler = fn +}