-
Notifications
You must be signed in to change notification settings - Fork 5
/
fasthttp.go
170 lines (150 loc) · 4.85 KB
/
fasthttp.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package webServer
import (
"fmt"
"github.com/fasthttp/router"
"github.com/techrail/ground/typs/appError"
"github.com/techrail/ground/utils"
"github.com/techrail/ground/webServer/middlewares"
"github.com/valyala/fasthttp"
"net"
"strconv"
)
const (
StateNotStarted = "NotStarted"
StateStarted = "Started"
StateShutdownRequested = "ShutdownRequested"
StateShutdownCompleted = "ShutdownCompleted"
)
type FastHttpServer struct {
Name string // Name of the server (used to identify it against another one, in case it is needed)
Router *router.Router
Server fasthttp.Server
BindPort int
EnableIpv6 bool
BlockOnStart bool // Should we block on start or not
currentState string // What is the current state of the server
middlewares map[string]MiddlewareSet
}
// NewLocalServer creates a basic new local server and returns it.
// It can then be modified and started (or started as it is)
func NewLocalServer() *FastHttpServer {
r := router.New()
mws := map[string]MiddlewareSet{
"Default": {
middlewares.SetRequestId,
middlewares.SetRandomVar,
middlewares.CheckShutdownRequested,
middlewares.CheckOpLogRequest,
},
}
return &FastHttpServer{
Router: r,
Server: fasthttp.Server{Handler: r.Handler},
BindPort: 8080,
EnableIpv6: false,
BlockOnStart: false,
currentState: StateNotStarted,
middlewares: mws,
}
}
// AddMiddlewareToSet will add a middleware to a single middleware set of a given name
// If a middleware set of that name does not exist, then one will be created.
func (s *FastHttpServer) AddMiddlewareToSet(m Middleware, name string) {
if _, ok := s.middlewares[name]; !ok {
s.middlewares[name] = MiddlewareSet{}
}
s.middlewares[name] = append(s.middlewares[name], m)
}
// AddMiddlewareSetToSet adds all the middlewares of one set to another set. Useful when you want to have some base
// middleware sets and you want to create others with those middlewares as common with the new ones
func (s *FastHttpServer) AddMiddlewareSetToSet(mwSet MiddlewareSet, name string) {
for _, m := range mwSet {
s.AddMiddlewareToSet(m, name)
}
}
// EraseMiddlewares removes all the middlewares from the server so that you can create a whole new set from scratch
func (s *FastHttpServer) EraseMiddlewares() {
s.middlewares = map[string]MiddlewareSet{}
}
// ListMiddlewareNames is supposed to return the list of middlewares in the server
func (s *FastHttpServer) ListMiddlewareNames() []string {
mwArr := []string{}
for setName, middlewareSet := range s.middlewares {
for _, m := range middlewareSet {
mwArr = append(mwArr, fmt.Sprintf("%v - %v", setName, utils.GetFunctionName(m, false)))
}
}
return mwArr
}
// GetMiddlewareSet returns the middleware set by the given name. If there is no middleware set by that name, a blank
// one is returned instead
func (s *FastHttpServer) GetMiddlewareSet(name string) MiddlewareSet {
if set, ok := s.middlewares[name]; ok {
return set
}
return MiddlewareSet{}
}
// WithMiddlewareSet will return a request handler which would contain all the middlewares given by name applied
// to the handler supplied to this function.
func (s *FastHttpServer) WithMiddlewareSet(name string, handler fasthttp.RequestHandler) fasthttp.RequestHandler {
mwSet := s.GetMiddlewareSet(name)
if len(mwSet) == 0 {
return handler
} else {
return chain(handler, mwSet...)
}
}
// Start starts the web server according to given parameters
func (s *FastHttpServer) Start() appError.Typ {
s.Server = fasthttp.Server{
Handler: s.Router.Handler,
}
var listener net.Listener
var err error
if s.EnableIpv6 {
listener, err = net.Listen("tcp", ":"+strconv.Itoa(s.BindPort))
} else {
listener, err = net.Listen("tcp4", ":"+strconv.Itoa(s.BindPort))
}
defer func(listener net.Listener) {
err := listener.Close()
if err != nil {
fmt.Printf("E#1MOCDG - Could not close listener. Error: %v", err)
}
}(listener)
if err != nil {
return appError.NewError(
appError.Error,
"1MHI99",
"Can't create the listener. Error: "+err.Error())
}
fn := func() appError.Typ {
e := s.Server.Serve(listener)
if e == nil {
return appError.BlankError
} else {
return appError.NewError(
appError.Error,
"1MHOPJ",
"Something went wrong when trying to start the server. Error: "+e.Error())
}
}
s.currentState = StateStarted
if s.BlockOnStart {
return fn()
} else {
go func() {
e := fn()
if e.IsNotBlank() {
fmt.Printf("E#1MOV7B - Server failed to either start or finish properly. Error: %v", e)
}
}()
}
return appError.BlankError
}
// stop will stop the server. It does so by setting the current state. The manager will notice the change
// and stop the server gracefully
// Important: The manager has to be adjusted to this behavior. Once done, export the function!
func (s *FastHttpServer) stop() {
s.currentState = StateShutdownRequested
}