-
Notifications
You must be signed in to change notification settings - Fork 2
/
http_server.go
105 lines (86 loc) · 2.61 KB
/
http_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
package httphelper
import (
"context"
"fmt"
"net/http"
"path"
"github.com/go-chi/chi"
"github.com/go-chi/chi/middleware"
"github.com/go-chi/cors"
log "github.com/sirupsen/logrus"
)
type Service interface {
HandleRequest(w http.ResponseWriter, r *http.Request)
}
type ServerEndpoint struct {
Path string
Service
}
func (*ServerEndpoint) HandleOptions(http.ResponseWriter, *http.Request) {
return
}
type HTTPServer struct {
Router *chi.Mux
Addr string
TLS bool
CertFile string
KeyFile string
}
func NewRouter() *chi.Mux {
router := chi.NewMux()
router.Use(middleware.Timeout(GatewayTimeout))
return router
}
func (srv *HTTPServer) SetUpCORS(allowedOrigins []string, debug bool) {
srv.Router.Use(cors.Handler(cors.Options{
AllowedOrigins: allowedOrigins,
AllowedMethods: []string{"POST", "OPTIONS"},
AllowedHeaders: []string{"Accept", "Content-Type", "Content-Length", "X-Auth-Token"},
ExposedHeaders: []string{"Accept", "Content-Type", "Content-Length", "X-Auth-Token"},
AllowCredentials: true,
MaxAge: 300, // Maximum value not ignored by any of major browsers
Debug: debug,
}))
}
func (srv *HTTPServer) AddServiceEndpoint(endpoint ServerEndpoint) {
hashEndpointPath := path.Join(endpoint.Path, HashEndpoint)
srv.Router.Post(endpoint.Path, endpoint.HandleRequest)
srv.Router.Post(hashEndpointPath, endpoint.HandleRequest)
srv.Router.Options(endpoint.Path, endpoint.HandleOptions)
srv.Router.Options(hashEndpointPath, endpoint.HandleOptions)
}
func (srv *HTTPServer) Serve(cancelCtx context.Context, serverReady context.CancelFunc) error {
server := &http.Server{
Addr: srv.Addr,
Handler: srv.Router,
ReadTimeout: ReadTimeout,
WriteTimeout: WriteTimeout,
IdleTimeout: IdleTimeout,
}
shutdownCtx, shutdownCancel := context.WithCancel(context.Background())
go func() {
<-cancelCtx.Done()
server.SetKeepAlivesEnabled(false) // disallow clients to create new long-running conns
shutdownWithTimeoutCtx, _ := context.WithTimeout(shutdownCtx, ShutdownTimeout)
defer shutdownCancel()
if err := server.Shutdown(shutdownWithTimeoutCtx); err != nil {
log.Warnf("could not gracefully shut down server: %s", err)
} else {
log.Debug("shut down HTTP server")
}
}()
log.Infof("starting HTTP server")
serverReady()
var err error
if srv.TLS {
err = server.ListenAndServeTLS(srv.CertFile, srv.KeyFile)
} else {
err = server.ListenAndServe()
}
if err != nil && err != http.ErrServerClosed {
return fmt.Errorf("error starting HTTP server: %v", err)
}
// wait for server to shut down gracefully
<-shutdownCtx.Done()
return nil
}