-
Notifications
You must be signed in to change notification settings - Fork 0
/
router.go
102 lines (86 loc) · 2.56 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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Package goapi is a lightweight opinionated router to bridge function call and http api.
package goapi
import (
"context"
"fmt"
"net/http"
"github.com/NaturalSelectionLabs/goapi/lib/middlewares"
"github.com/NaturalSelectionLabs/goapi/lib/openapi"
"github.com/NaturalSelectionLabs/jschema"
"github.com/xeipuuv/gojsonschema"
)
// Router for routing http requests to handlers.
// It implements the [middlewares.Middleware] interface.
type Router struct {
Schemas jschema.Schemas
middlewares []middlewares.Middleware
operations []*Operation
sever *http.Server
}
// New is a shortcut for:
//
// NewRouter().Group("")
func New() *Group {
return NewRouter().Group("")
}
// NewRouter creates a new router.
func NewRouter() *Router {
s := jschema.NewWithInterfaces("#/components/schemas", Interfaces)
s.HijackTime()
s.HijackJSONRawMessage()
s.HijackBigInt()
return &Router{
middlewares: []middlewares.Middleware{},
Schemas: s,
}
}
// ServerHandler with a 404 middleware at the end.
func (r *Router) ServerHandler() http.Handler {
return r.Handler(http.HandlerFunc(func(w http.ResponseWriter, rq *http.Request) {
middlewares.ResponseError(w, http.StatusNotFound, &openapi.Error{
Code: openapi.CodeNotFound,
Message: fmt.Sprintf("path not found: %s %s", rq.Method, rq.URL.Path),
Target: rq.URL.Path,
InnerError: []any{rq.Method, rq.URL.Path},
})
}))
}
// Start listen on addr with the [Router.ServerHandler].
func (r *Router) Start(addr string) error {
r.sever = &http.Server{
Addr: addr,
Handler: r.ServerHandler(),
}
return r.sever.ListenAndServe()
}
// Shutdown the server.
func (r *Router) Shutdown(ctx context.Context) error {
return r.sever.Shutdown(ctx)
}
// Use a middleware to the router.
func (r *Router) Use(middlewares ...middlewares.Middleware) {
r.middlewares = append(r.middlewares, middlewares...)
}
// Handler implements the [middlewares.Middleware] interface.
// It makes the router itself a middleware.
func (r *Router) Handler(next http.Handler) http.Handler {
return middlewares.Chain(r.middlewares...).Handler(next)
}
// Group creates a new group with the given prefix.
func (r *Router) Group(prefix string) *Group {
g := &Group{router: r}
return g.Group(prefix)
}
// AddFormatChecker for json schema validation.
// Such as a struct:
//
// type User struct {
// ID string `format:"my-id"`
// }
//
// You can add a format checker for "id" like:
//
// AddFormatChecker("my-id", checker)
func (r *Router) AddFormatChecker(name string, c gojsonschema.FormatChecker) {
gojsonschema.FormatCheckers.Add(name, c)
}