-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapi.go
More file actions
112 lines (93 loc) · 2.93 KB
/
api.go
File metadata and controls
112 lines (93 loc) · 2.93 KB
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
103
104
105
106
107
108
109
110
111
112
package gateway
import (
"bytes"
"reflect"
"time"
)
type ServiceInfo struct {
*ServiceConfig
State string `json:"state"`
}
type infoResponse struct {
TotalConnectionService uint64 `json:"totalConnectionServed"`
IsProd bool `json:"isProd"`
AreMiddlewaresEnabled bool `json:"areMiddlewaresEnabled"`
Uptime string `json:"uptime"`
Services []*ServiceInfo `json:"services"`
}
type updateServiceStateRequest struct {
ServiceName string `json:"serviceName"`
}
const (
IncomingDecodedKey ContextKey = "incomingDecoded"
X_GW_HEADER_KEY string = "X-GATEWAY-KEY"
)
type decodeFunction func([]byte) (any, error)
// getCleanedBody makes the incoming request body as tight as possible.
func getCleanedBody(b []byte) []byte {
b = bytes.ReplaceAll(b, []byte(" "), []byte(""))
return bytes.ReplaceAll(b, []byte("\n"), []byte(""))
}
// validateIncomingRequest validates all the incoming requests by its header key.
func validateIncomingRequest(g *Gateway, df decodeFunction) MiddlewareFunc {
return func(ctx Context, next HandlerFunc) {
b := getCleanedBody(ctx.GetBody())
var (
key = ctx.GetRequestHeader(X_GW_HEADER_KEY)
plain = append(b, []byte(g.info.secretKey)...)
)
// If the value if the header is not deeply equal to
// the one that we constructed based on the shared secret key
// we simply return with 401.
if h := createHash(plain); !reflect.DeepEqual(h, []byte(key)) {
ctx.SendUnauthorized()
return
}
incoming, err := df(b)
if err != nil {
ctx.SendUnauthorized()
return
}
ctx.BindValue(IncomingDecodedKey, incoming)
next(ctx)
}
}
// serviceStateUpdateHandler returns a HandlerFunc which will update the corresponding service's state.
func serviceStateUpdateHandler(g *Gateway) HandlerFunc {
return func(ctx Context) {
inc, ok := ctx.GetBindedValue(IncomingDecodedKey).(*updateServiceStateRequest)
if !ok {
ctx.SendUnauthorized()
return
}
if inc.ServiceName == "" {
ctx.SendUnauthorized()
return
}
g.serviceRegisty.setServiceAvailable(inc.ServiceName)
ctx.SendOk()
}
}
// getSystemInfoHandler returns a response with the Gateway's info.
// Currently it only returns the slice of registered services – with all its info –
// the system's uptime and the count of served connections so far.
func getSystemInfoHandler(g *Gateway) HandlerFunc {
return func(ctx Context) {
services := g.serviceRegisty.getAllServices()
info := make([]*ServiceInfo, len(services))
for i, e := range services {
info[i] = &ServiceInfo{
ServiceConfig: e.ServiceConfig,
State: stateTexts[e.state],
}
}
res := &infoResponse{
TotalConnectionService: ctx.GetContextId(),
Services: info,
IsProd: g.isProd(),
AreMiddlewaresEnabled: g.areMiddlewaresEnabled(),
Uptime: getElapsedTime(g.info.startTime, time.Now()),
}
ctx.SendJson(res)
}
}