-
Notifications
You must be signed in to change notification settings - Fork 2
/
fresh.go
146 lines (128 loc) · 2.67 KB
/
fresh.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
package fresh
import (
httpContext "context"
"log"
"net/http"
"os"
"time"
"net"
"os/signal"
"strconv"
"syscall"
)
// Main Fresh structure
type (
fresh struct {
config *Config
router *router
server *http.Server
}
context struct {
request request
response response
parameters map[string]string
}
Fresh interface {
Rest
Stop() error
Start() error
Config() *Config
Group(string) Group
}
Context interface {
Request() Request
Response() Response
Writer(http.ResponseWriter)
}
HandlerFunc func(Context) error
)
// New Fresh instance
func New() Fresh {
fresh := fresh{}
// Fresh config
fresh.config = &Config{}
fresh.config.init(&fresh)
// Server setting
fresh.server = new(http.Server)
// Fresh router
fresh.router = &router{&fresh, &route{}, make(map[string]string)}
wd, _ := os.Executable()
if fresh.config.read(wd) != nil {
fresh.config.Host = "127.0.0.1"
fresh.config.Port = randPort(fresh.config.Host, 3000)
}
return &fresh
}
// Shutdown server
func (f *fresh) Stop() error {
ctx, cancel := httpContext.WithTimeout(httpContext.Background(), 5*time.Second)
f.server.Shutdown(ctx)
cancel()
f.config.log("Server shutdown")
return nil
}
// Start HTTP server
func (f *fresh) Start() error {
shutdown := make(chan os.Signal)
port := strconv.Itoa(f.config.Port)
signal.Notify(shutdown, os.Interrupt, syscall.SIGTERM)
listener, err := net.Listen("tcp", f.config.Host+":"+port)
if err != nil {
log.Fatal(err)
return err
}
go func() {
f.config.banner()
f.config.log("Server listen on", f.config.Host+":"+port)
f.server.Handler = f.router
// default route
if f.router.route.children == nil {
f.GET("/", func(c Context) error {
return c.Response().Raw(http.StatusOK, welcome)
})
}
if f.config.Router != nil && f.config.Router.Print {
PrintRouter(f.router)
}
// check for tsl before serve
if f.config.TSL != nil {
f.config.tsl()
}
f.server.Serve(listener)
}()
<-shutdown
f.Stop()
return nil
}
// Config return server settings
func (f *fresh) Config() *Config {
return f.config
}
// Group registration
func (f *fresh) Group(path string) Group {
g := group{
parent: f,
route: &route{
path: path,
},
}
return &g
}
// Return context request
func (c *context) Request() Request {
return &c.request
}
// Return context response
func (c *context) Response() Response {
return &c.response
}
// Overwrite http writer
func (c *context) Writer(w http.ResponseWriter) {
c.response.w = w
}
// Init set context request and response
func (c *context) init(r *http.Request, w http.ResponseWriter) {
c.response = response{w: w, r: r}
c.request = request{r: r}
c.request.setRouteParam(c.parameters)
}