github.com/thiagoyeds/go-cloud@v0.26.0/server/server.go (about) 1 // Copyright 2018 The Go Cloud Development Kit Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package server provides a preconfigured HTTP server with diagnostic hooks. 16 package server // import "gocloud.dev/server" 17 18 import ( 19 "context" 20 "fmt" 21 "net/http" 22 "sync" 23 "time" 24 25 "github.com/google/wire" 26 "gocloud.dev/server/driver" 27 "gocloud.dev/server/health" 28 "gocloud.dev/server/requestlog" 29 30 "go.opencensus.io/plugin/ochttp" 31 "go.opencensus.io/trace" 32 ) 33 34 // Set is a Wire provider set that produces a *Server given the fields of 35 // Options. 36 var Set = wire.NewSet( 37 New, 38 wire.Struct(new(Options), "RequestLogger", "HealthChecks", "TraceExporter", "DefaultSamplingPolicy", "Driver"), 39 wire.Value(&DefaultDriver{}), 40 wire.Bind(new(driver.Server), new(*DefaultDriver)), 41 ) 42 43 // Server is a preconfigured HTTP server with diagnostic hooks. 44 // The zero value is a server with the default options. 45 type Server struct { 46 reqlog requestlog.Logger 47 handler http.Handler 48 wrappedHandler http.Handler 49 healthHandler health.Handler 50 te trace.Exporter 51 sampler trace.Sampler 52 once sync.Once 53 driver driver.Server 54 } 55 56 // Options is the set of optional parameters. 57 type Options struct { 58 // RequestLogger specifies the logger that will be used to log requests. 59 RequestLogger requestlog.Logger 60 61 // HealthChecks specifies the health checks to be run when the 62 // /healthz/readiness endpoint is requested. 63 HealthChecks []health.Checker 64 65 // TraceExporter exports sampled trace spans. 66 TraceExporter trace.Exporter 67 68 // DefaultSamplingPolicy is a function that takes a 69 // trace.SamplingParameters struct and returns a true or false decision about 70 // whether it should be sampled and exported. 71 DefaultSamplingPolicy trace.Sampler 72 73 // Driver serves HTTP requests. 74 Driver driver.Server 75 } 76 77 // New creates a new server. New(nil, nil) is the same as new(Server). 78 func New(h http.Handler, opts *Options) *Server { 79 srv := &Server{handler: h} 80 if opts != nil { 81 srv.reqlog = opts.RequestLogger 82 srv.te = opts.TraceExporter 83 for _, c := range opts.HealthChecks { 84 srv.healthHandler.Add(c) 85 } 86 srv.sampler = opts.DefaultSamplingPolicy 87 srv.driver = opts.Driver 88 } 89 return srv 90 } 91 92 func (srv *Server) init() { 93 srv.once.Do(func() { 94 if srv.te != nil { 95 trace.RegisterExporter(srv.te) 96 } 97 if srv.sampler != nil { 98 trace.ApplyConfig(trace.Config{DefaultSampler: srv.sampler}) 99 } 100 if srv.driver == nil { 101 srv.driver = NewDefaultDriver() 102 } 103 if srv.handler == nil { 104 srv.handler = http.DefaultServeMux 105 } 106 // Setup health checks, /healthz route is taken by health checks by default. 107 // Note: App Engine Flex uses /_ah/health by default, which can be changed 108 // in app.yaml. We may want to do an auto-detection for flex in future. 109 const healthPrefix = "/healthz/" 110 111 mux := http.NewServeMux() 112 mux.HandleFunc(healthPrefix+"liveness", health.HandleLive) 113 mux.Handle(healthPrefix+"readiness", &srv.healthHandler) 114 h := srv.handler 115 if srv.reqlog != nil { 116 h = requestlog.NewHandler(srv.reqlog, h) 117 } 118 h = &ochttp.Handler{ 119 Handler: h, 120 IsPublicEndpoint: true, 121 } 122 mux.Handle("/", h) 123 srv.wrappedHandler = mux 124 }) 125 } 126 127 // ListenAndServe is a wrapper to use wherever http.ListenAndServe is used. 128 // It wraps the http.Handler provided to New with a handler that handles tracing and 129 // request logging. If the handler is nil, then http.DefaultServeMux will be used. 130 // A configured Requestlogger will log all requests except HealthChecks. 131 func (srv *Server) ListenAndServe(addr string) error { 132 srv.init() 133 return srv.driver.ListenAndServe(addr, srv.wrappedHandler) 134 } 135 136 // ListenAndServeTLS is a wrapper to use wherever http.ListenAndServeTLS is used. 137 // It wraps the http.Handler provided to New with a handler that handles tracing and 138 // request logging. If the handler is nil, then http.DefaultServeMux will be used. 139 // A configured Requestlogger will log all requests except HealthChecks. 140 func (srv *Server) ListenAndServeTLS(addr, certFile, keyFile string) error { 141 // Check if the driver implements the optional interface. 142 tlsDriver, ok := srv.driver.(driver.TLSServer) 143 if !ok { 144 return fmt.Errorf("driver %T does not support ListenAndServeTLS", srv.driver) 145 } 146 srv.init() 147 return tlsDriver.ListenAndServeTLS(addr, certFile, keyFile, srv.wrappedHandler) 148 } 149 150 // Shutdown gracefully shuts down the server without interrupting any active connections. 151 func (srv *Server) Shutdown(ctx context.Context) error { 152 if srv.driver == nil { 153 return nil 154 } 155 return srv.driver.Shutdown(ctx) 156 } 157 158 // DefaultDriver implements the driver.Server interface. The zero value is a valid http.Server. 159 type DefaultDriver struct { 160 Server http.Server 161 } 162 163 // NewDefaultDriver creates a driver with an http.Server with default timeouts. 164 func NewDefaultDriver() *DefaultDriver { 165 return &DefaultDriver{ 166 Server: http.Server{ 167 ReadTimeout: 30 * time.Second, 168 WriteTimeout: 30 * time.Second, 169 IdleTimeout: 120 * time.Second, 170 }, 171 } 172 } 173 174 // ListenAndServe sets the address and handler on DefaultDriver's http.Server, 175 // then calls ListenAndServe on it. 176 func (dd *DefaultDriver) ListenAndServe(addr string, h http.Handler) error { 177 dd.Server.Addr = addr 178 dd.Server.Handler = h 179 return dd.Server.ListenAndServe() 180 } 181 182 // ListenAndServeTLS sets the address and handler on DefaultDriver's http.Server, 183 // then calls ListenAndServeTLS on it. 184 // 185 // DefaultDriver.Server.TLSConfig may be set to configure additional TLS settings. 186 func (dd *DefaultDriver) ListenAndServeTLS(addr, certFile, keyFile string, h http.Handler) error { 187 dd.Server.Addr = addr 188 dd.Server.Handler = h 189 return dd.Server.ListenAndServeTLS(certFile, keyFile) 190 } 191 192 // Shutdown gracefully shuts down the server without interrupting any active connections, 193 // by calling Shutdown on DefaultDriver's http.Server 194 func (dd *DefaultDriver) Shutdown(ctx context.Context) error { 195 return dd.Server.Shutdown(ctx) 196 }