-
Notifications
You must be signed in to change notification settings - Fork 211
/
http_server.go
97 lines (88 loc) · 2.52 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
package grpcserver
import (
"context"
"errors"
"fmt"
"net"
"net/http"
"time"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"go.uber.org/zap"
"golang.org/x/sync/errgroup"
)
// JSONHTTPServer is a JSON http server providing the Spacemesh API.
// It is implemented using a grpc-gateway. See https://github.com/grpc-ecosystem/grpc-gateway .
type JSONHTTPServer struct {
listener string
logger *zap.Logger
// BoundAddress contains the address that the server bound to, useful if
// the server uses a dynamic port. It is set during startup and can be
// safely accessed after Start has completed (I.E. the returned channel has
// been waited on)
BoundAddress string
server *http.Server
eg errgroup.Group
}
// NewJSONHTTPServer creates a new json http server.
func NewJSONHTTPServer(listener string, lg *zap.Logger) *JSONHTTPServer {
return &JSONHTTPServer{
logger: lg,
listener: listener,
}
}
// Shutdown stops the server.
func (s *JSONHTTPServer) Shutdown(ctx context.Context) error {
s.logger.Debug("stopping json-http service...")
if s.server != nil {
err := s.server.Shutdown(ctx)
if errors.Is(err, http.ErrServerClosed) {
return nil
}
if err != nil {
return fmt.Errorf("shutdown: %w", err)
}
}
err := s.eg.Wait()
if errors.Is(err, http.ErrServerClosed) {
return nil
}
return err
}
// StartService starts the json api server and listens for status (started, stopped).
func (s *JSONHTTPServer) StartService(
ctx context.Context,
services ...ServiceAPI,
) error {
// At least one service must be enabled
if len(services) == 0 {
s.logger.Error("not starting grpc gateway service; at least one service must be enabled")
return errors.New("no services provided")
}
// register each individual, enabled service
mux := runtime.NewServeMux()
for _, svc := range services {
if err := svc.RegisterHandlerService(mux); err != nil {
return fmt.Errorf("registering service %s with grpc gateway failed: %w", svc, err)
}
}
s.logger.Info("starting grpc gateway server", zap.String("address", s.listener))
lis, err := net.Listen("tcp", s.listener)
if err != nil {
return fmt.Errorf("listening on %s: %w", s.listener, err)
}
s.BoundAddress = lis.Addr().String()
s.server = &http.Server{
MaxHeaderBytes: 1 << 21,
ReadTimeout: 15 * time.Second,
WriteTimeout: 15 * time.Second,
Handler: mux,
}
s.eg.Go(func() error {
if err := s.server.Serve(lis); err != nil {
s.logger.Error("serving grpc server", zap.Error(err))
return nil
}
return nil
})
return nil
}