github.com/SaurabhDubey-Groww/go-cloud@v0.0.0-20221124105541-b26c29285fd8/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  }