/
server.go
114 lines (103 loc) · 2.7 KB
/
server.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
package server
import (
"context"
"fmt"
"net/http"
"os"
"os/signal"
"time"
"github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/labstack/gommon/log"
"github.com/vuduongtp/go-core/pkg/server/middleware/secure"
"github.com/vuduongtp/go-core/pkg/util/logger"
"github.com/vuduongtp/go-logadapter"
)
// Config represents server specific config
type Config struct {
Stage string
Port int
ReadTimeout int
WriteTimeout int
Debug bool
AllowOrigins []string
IsEnableSwagger bool
SwaggerPath string
}
var (
// DefaultConfig for the API server
DefaultConfig = Config{
Stage: "development",
Port: 8080,
ReadTimeout: 10,
WriteTimeout: 5,
Debug: true,
AllowOrigins: []string{"*"},
}
)
func (c *Config) fillDefaults() {
if c.Stage == "" {
c.Stage = DefaultConfig.Stage
}
if c.Port == 0 {
c.Port = DefaultConfig.Port
}
if c.ReadTimeout == 0 {
c.ReadTimeout = DefaultConfig.ReadTimeout
}
if c.WriteTimeout == 0 {
c.WriteTimeout = DefaultConfig.WriteTimeout
}
if c.AllowOrigins == nil && len(c.AllowOrigins) == 0 {
c.AllowOrigins = DefaultConfig.AllowOrigins
}
}
// New instantates new Echo server
func New(cfg *Config) *echo.Echo {
cfg.fillDefaults()
e := echo.New()
e.Validator = NewValidator()
e.HTTPErrorHandler = NewErrorHandler(e).Handle
e.Binder = NewBinder()
e.Debug = cfg.Debug
e.Logger = logadapter.NewEchoLogger()
e.Use(logadapter.NewEchoLoggerMiddleware())
if e.Debug {
e.Logger.SetLevel(log.DEBUG)
e.Use(secure.BodyDump())
} else {
e.Logger.SetLevel(log.ERROR)
}
e.Server.Addr = fmt.Sprintf(":%d", cfg.Port)
e.Server.ReadTimeout = time.Duration(cfg.ReadTimeout) * time.Minute
e.Server.WriteTimeout = time.Duration(cfg.WriteTimeout) * time.Minute
e.Use(middleware.Recover(), secure.Headers(), secure.CORS(&secure.Config{AllowOrigins: cfg.AllowOrigins}))
return e
}
// Start starts echo server
func Start(e *echo.Echo, isDevelopment bool) {
// hide verbose logs
e.HideBanner = true
// graceful shutdown
// Start server
go func() {
if err := e.StartServer(e.Server); err != nil {
if err == http.ErrServerClosed {
logger.Info("shutting down the server")
} else {
logger.Error("shutting down the server", err)
}
}
}()
// Wait for interrupt signal to gracefully shutdown the server with
// a timeout of 10 seconds.
quit := make(chan os.Signal)
signal.Notify(quit, os.Interrupt)
<-quit
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := e.Shutdown(ctx); err != nil {
// Error from closing listeners, or context timeout:
logger.Error(fmt.Sprintf("⇨ http server shutting down error: %v\n", err))
}
}