-
Notifications
You must be signed in to change notification settings - Fork 0
/
router.go
88 lines (71 loc) · 2.31 KB
/
router.go
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package webhttp
import (
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"github.com/go-chi/chi"
"github.com/pavelmemory/faceit-users/internal"
"github.com/pavelmemory/faceit-users/internal/logging"
)
// NewRouter returns initialized HTTP router.
// It sets up all required middlewares and bindings for endpoints.
func NewRouter(logger logging.Logger) chi.Router {
router := chi.NewRouter()
router.Use(InjectLogger(logger)) // TODO: CORS, caching, tracing, metrics, etc.
infoHandler := InfoHandler{}
infoHandler.Register(router)
router.With(LogRequest()).NotFound(undefined)
router.With(LogRequest()).MethodNotAllowed(undefined)
return router
}
func undefined(w http.ResponseWriter, r *http.Request) {
logging.FromContext(r.Context()).Debug("request is not implemented")
w.WriteHeader(http.StatusNotImplemented)
}
// WriteError sends an error response back to the client.
func WriteError(w http.ResponseWriter, logger logging.Logger, err error) {
resp := ErrorResponse{StatusCode: http.StatusInternalServerError}
if logger.IsDebug() {
// sends error details back to the client only in debugging mode
resp.Cause = err
}
switch {
case errors.Is(err, internal.ErrBadInput):
resp.StatusCode = http.StatusBadRequest
case errors.Is(err, internal.ErrNotUnique):
resp.StatusCode = http.StatusConflict
case errors.Is(err, internal.ErrNotFound):
resp.StatusCode = http.StatusNotFound
}
resp.Write(logger, w)
}
// ErrorResponse aggregates error information into the struct and know how to send it back to the client.
type ErrorResponse struct {
// StatusCode status code that should be returned.
StatusCode int
// Cause is an error that needs to be placed as a message describing what was wrong.
Cause error
}
func (er ErrorResponse) Write(logger logging.Logger, w http.ResponseWriter) {
w.WriteHeader(er.StatusCode)
if er.Cause == nil {
return
}
if err := Encode(w, er.Cause.Error()); err != nil {
logger.WithError(err).Error("send response")
}
}
func Decode(reader io.Reader, dst interface{}) error {
if err := json.NewDecoder(reader).Decode(dst); err != nil {
return fmt.Errorf("decode into %T: %w", dst, err)
}
return nil
}
func Encode(writer io.Writer, src interface{}) error {
if err := json.NewEncoder(writer).Encode(src); err != nil {
return fmt.Errorf("encode %T: %w", src, err)
}
return nil
}