all repos — homestead @ c0f110119e434f188f5959c48570df12121cc663

Code for my website

shared/http/mux.go (view raw)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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
}