This repository has been archived by the owner on Feb 23, 2023. It is now read-only.
/
server.go
128 lines (111 loc) · 3.12 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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package cmd
import (
"compress/gzip"
"fmt"
"net/http"
"os"
"syscall"
"github.com/bryk-io/dlt4eu/service"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.bryk.io/x/cli"
"go.bryk.io/x/net/graphql"
"go.bryk.io/x/net/graphql/extension/tracing"
"go.bryk.io/x/net/loader"
"go.bryk.io/x/net/middleware"
"go.bryk.io/x/observability"
)
var helper *loader.Helper
var serverCmd = &cobra.Command{
Use: "server",
Short: "Start a GraphQL server instance to handle incoming requests",
Example: "dlt4eu server --config file.yaml",
RunE: runServer,
}
func init() {
segments := []string{
loader.SegmentHTTP,
loader.SegmentGraphQL,
loader.SegmentObservability,
loader.SegmentMiddlewareCORS,
loader.SegmentMiddlewareMetadata,
}
helper = loader.New()
if err := cli.SetupCommandParams(serverCmd, helper.Params(segments...)); err != nil {
panic(err)
}
rootCmd.AddCommand(serverCmd)
}
func runServer(_ *cobra.Command, _ []string) error {
// Load general configuration settings.
if err := viper.Unmarshal(helper.Data); err != nil {
return err
}
// Load service handler settings.
conf := new(service.Config)
if err := viper.UnmarshalKey("service", conf); err != nil {
return err
}
// Get observability operator. Discard tracer output and keep
// only logging and metrics.
oopSettings := helper.Observability()
oop, err := observability.NewOperator(oopSettings...)
if err != nil {
return err
}
// Get service handler instance.
handler, err := service.New(conf)
if err != nil {
return err
}
// Get GraphQL server instance.
srv, err := graphql.NewServer(handler.Schema(), helper.GraphQL()...)
if err != nil {
return err
}
// Apply HTTP middleware.
srv.Use(middleware.GzipCompression(gzip.DefaultCompression))
srv.Use(middleware.ProxyHeaders())
srv.Use(middleware.CORS(helper.MiddlewareCORS()))
srv.Use(middleware.ContextMetadata(helper.MiddlewareMetadata()))
srv.Use(customHeaders())
srv.Use(oop.HTTPServerMiddleware())
// Apply GraphQL extensions.
srv.UseHandlerExtension(tracing.FieldTracing(oop, false))
// Start server
router := http.NewServeMux()
router.Handle("/graphql", srv.GetHandler())
router.HandleFunc("/ping", pingHandler())
oop.Infof("waiting for requests on: http://localhost:%d/graphql", helper.Data.HTTP.Port)
go func() {
_ = http.ListenAndServe(fmt.Sprintf(":%d", helper.Data.HTTP.Port), router)
}()
// wait for system signals
<-cli.SignalsHandler([]os.Signal{
syscall.SIGHUP,
syscall.SIGINT,
syscall.SIGTERM,
syscall.SIGQUIT,
})
// Close server
oop.Info("closing server")
handler.Shutdown()
return nil
}
// Attach version information as HTTP headers on all responses
func customHeaders() func(handler http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("x-dlt4eu-version", coreVersion)
w.Header().Set("x-dlt4eu-build", buildCode)
next.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
}
// Manage a basic (not instrumented) ping request
func pingHandler() http.HandlerFunc {
return func(res http.ResponseWriter, _ *http.Request) {
_, _ = res.Write([]byte("ok"))
}
}