server

package
v0.0.0-...-b839ebc Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 14, 2016 License: Apache-2.0 Imports: 33 Imported by: 0

Documentation

Overview

Package server is the bulk of the toolkit and relies on `config` for any managing `Server` implementations. A server must implement the following interface:

// Server is the basic interface that defines what expect from any server.
type Server interface {
    Register(...Service) error
    Start() error
    Stop() error
}

The package offers 2 server implementations:

`SimpleServer`, which is capable of handling basic HTTP and JSON requests via 3 of the available `Service` implementations: `SimpleService`, `JSONService`, and `MixedService`. A service and these implementations will be defined below.

`RPCServer`, which is capable of serving a gRPC server on one port and JSON endpoints on another. This kind of server can only handle the `RPCService` implementation.

The `Service` interface is minimal to allow for maximum flexibility:

type Service interface {
    Prefix() string

    // Middleware provides a hook for service-wide middleware
    Middleware(http.Handler) http.Handler
}

The 3 service types that are accepted and hostable on the `SimpleServer`:

type SimpleService interface {
    Service

    // router - method - func
    Endpoints() map[string]map[string]http.HandlerFunc
}

type JSONService interface {
    Service

    // router - method - func
    JSONEndpoints() map[string]map[string]JSONEndpoint
    // JSONMiddleware provides a hook for service-wide middleware around JSONEndpoints.
    JSONMiddleware(JSONEndpoint) JSONEndpoint
}

type MixedService interface {
    Service

    // route - method - func
    Endpoints() map[string]map[string]http.HandlerFunc

    // route - method - func
    JSONEndpoints() map[string]map[string]JSONEndpoint
    // JSONMiddleware provides a hook for service-wide middleware around JSONEndpoints.
    JSONMiddleware(JSONEndpoint) JSONEndpoint
}

Where a `JSONEndpoint` is defined as:

type JSONEndpoint func(*http.Request) (int, interface{}, error)

Also, the one service type that works with an `RPCServer`:

type RPCService interface {
    Service

    Service() (grpc.ServiceDesc, interface{})

    // route - method - func
    JSONEndpoints() map[string]map[string]JSONEndpoint
    // JSONMiddleware provides a hook for service-wide middleware around JSONEndpoints.
    JSONMiddlware(JSONEndpoint) JSONEndpoint
}

The `Middleware(..)` functions offer each service a 'hook' to wrap each of its endpoints. This may be handy for adding additional headers or context to the request. This is also the point where other, third-party middleware could be easily be plugged in (ie. oauth, tracing, metrics, logging, etc.)

Examples

Check out the gizmo/examples/servers directory to see several reference implementations.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ESXShutdownTimeout is the hard cut off kill the server while the ESXHealthCheck is waiting
	// for the server to be inactive.
	ESXShutdownTimeout = 180 * time.Second
	// ESXShutdownPollInterval sets the duration for how long ESXHealthCheck will wait between
	// each NumActiveRequests poll in WaitForZero.
	ESXShutdownPollInterval = 1 * time.Second
	// ESXLoadBalancerNotReadyDuration is the amount of time ESXHealthCheck will wait after
	// sending a 'bad' status to the LB during a graceful shutdown.
	ESXLoadBalancerNotReadyDuration = 15 * time.Second
)
View Source
var (
	// Name is used for status and logging.
	Name = "nyt-awesome-go-server"
	// Log is the global logger for the server. It will take care of logrotate
	// and it can accept 'fields' to include with each log line: see LogWithFields(r).
	Log = logrus.New()
)
View Source
var UnexpectedServerError = []byte("unexpected server error")

UnexpectedServerError is returned with a 500 status code when SimpleServer recovers from a panic in a request.

View Source
var Version string

Version is meant to be set with the current package version at build time.

Functions

func AddIPToContext

func AddIPToContext(r *http.Request)

AddIPToContext will attempt to pull an IP address out of the request and set it into a gorilla context.

func CORSHandler

func CORSHandler(f http.Handler, originSuffix string) http.Handler

CORSHandler is a middleware func for setting all headers that enable CORS. If an originSuffix is provided, a strings.HasSuffix check will be performed before adding any CORS header. If an empty string is provided, any Origin header found will be placed into the CORS header. If no Origin header is found, no headers will be added.

func ContextFields

func ContextFields(r *http.Request) map[string]interface{}

ContextFields will take a request and convert a context map to logrus Fields.

func ContextToHTTP

func ContextToHTTP(ctx context.Context, ep ContextHandler) http.Handler

ContextToHTTP is a middleware func to convert a ContextHandler an http.Handler.

func ContextWithForwardForIP

func ContextWithForwardForIP(ctx netContext.Context, r *http.Request) netContext.Context

ContextWithForwardForIP returns new context with forward for ip.

func ContextWithUserIP

func ContextWithUserIP(ctx netContext.Context, r *http.Request) netContext.Context

ContextWithUserIP returns new context with user ip address.

func GetForwardedIP

func GetForwardedIP(r *http.Request) string

GetForwardedIP returns the "X-Forwarded-For" header value.

func GetIP

func GetIP(r *http.Request) (string, error)

GetIP returns the IP address for the given request.

func Init

func Init(name string, scfg *config.Server)

Init will set up our name, logging, healthchecks and parse flags. If DefaultServer isn't set, this func will set it to a `SimpleServer` listening on `Config.Server.HTTPPort`.

func JSONPHandler

func JSONPHandler(f http.Handler) http.Handler

JSONPHandler is a middleware func for wrapping response body with JSONP.

func JSONToHTTP

func JSONToHTTP(ep JSONEndpoint) http.Handler

JSONToHTTP is the middleware func to convert a JSONEndpoint to an http.HandlerFunc.

func LogRPCWithFields

func LogRPCWithFields(log *logrus.Logger, ctx context.Context) *logrus.Entry

LogRPCWithFields will feed any request context into a logrus Entry.

func LogWithFields

func LogWithFields(r *http.Request) *logrus.Entry

LogWithFields will feed any request context into a logrus Entry.

func MetadataToFields

func MetadataToFields(md metadata.MD) logrus.Fields

MetadataToFields will accept all values from a metadata.MD and create logrus.Fields with the same set.

func MetricsRegistryName

func MetricsRegistryName() string

MetricsRegistryName returns "apps.{hostname prefix}", which is the convention used in NYT ESX environment.

func MonitorRPCRequest

func MonitorRPCRequest() func(ctx context.Context, methodName string, err error)

MonitorRPCRequest should be deferred by any RPC method that would like to have metrics and access logging, participate in graceful shutdowns and safely recover from panics.

func NoCacheHandler

func NoCacheHandler(f http.Handler) http.Handler

NoCacheHandler is a middleware func for setting the Cache-Control to no-cache.

func Register

func Register(svc Service) error

Register will add a new Service to the DefaultServer.

func RegisterAccessLogger

func RegisterAccessLogger(cfg *config.Server, handler http.Handler) http.Handler

RegisterAccessLogger will wrap a logrotate-aware Apache-style access log handler around the given handler if an access log location is provided by the config.

func RegisterProfiler

func RegisterProfiler(cfg *config.Server, mx *mux.Router)

RegisterProfiler will add handlers for pprof endpoints if the config has them enabled.

func Run

func Run() error

Run will start the DefaultServer and set it up to Stop() on a kill signal.

func SetLogLevel

func SetLogLevel(scfg *config.Server)

SetLogLevel will set the appropriate logrus log level given the server config.

func StartServerMetrics

func StartServerMetrics(cfg *config.Server)

StartServerMetrics will start emitting metrics to the DefaultRegistry if a Graphite host name is given in the config.

func Stop

func Stop() error

Stop will stop the default server.

Types

type ActivityMonitor

type ActivityMonitor struct {
	// contains filtered or unexported fields
}

ActivityMonitor can be used to count and share the number of active requests.

func NewActivityMonitor

func NewActivityMonitor() *ActivityMonitor

NewActivityMonitor will return a new ActivityMonitor instance.

func (*ActivityMonitor) Active

func (a *ActivityMonitor) Active() bool

Active returns true if there are requests currently in flight.

func (*ActivityMonitor) CountRequest

func (a *ActivityMonitor) CountRequest()

CountRequest will increment the request count and signal the activity monitor to stay active. Call this in your server when you receive a request.

func (*ActivityMonitor) NumActiveRequests

func (a *ActivityMonitor) NumActiveRequests() uint32

NumActiveRequests returns the number of in-flight requests currently running on this server.

func (*ActivityMonitor) UncountRequest

func (a *ActivityMonitor) UncountRequest()

UncountRequest will decrement the active request count. Best practice is to `defer` this function call directly after calling CountRequest().

type ContextHandler

type ContextHandler interface {
	ServeHTTPContext(context.Context, http.ResponseWriter, *http.Request)
}

ContextHandler is an equivalent to http.Handler but with additional param.

type ContextHandlerFunc

type ContextHandlerFunc func(context.Context, http.ResponseWriter, *http.Request)

ContextHandlerFunc is an equivalent to SimpleService's http.HandlerFunc.

func (ContextHandlerFunc) ServeHTTPContext

func (h ContextHandlerFunc) ServeHTTPContext(ctx context.Context, rw http.ResponseWriter, req *http.Request)

ServeHTTPContext is an implementation of ContextHandler interface.

type ContextKey

type ContextKey int

ContextKey used to create context keys.

const (
	// UserIPKey is key to set/retrieve value from context.
	UserIPKey ContextKey = 0

	// UserForwardForIPKey is key to set/retrieve value from context.
	UserForwardForIPKey ContextKey = 1
)

type ContextService

type ContextService interface {
	Service

	// route - method - func
	ContextEndpoints() map[string]map[string]ContextHandlerFunc
	ContextMiddleware(ContextHandler) ContextHandler
}

ContextService is an interface defining a service that is made up of ContextHandler.

type CounterByStatusXX

type CounterByStatusXX struct {
	// contains filtered or unexported fields
}

CounterByStatusXX is an http.Handler that counts responses by the first digit of their HTTP status code via go-metrics.

func CountedByStatusXX

func CountedByStatusXX(handler http.Handler, name string, registry metrics.Registry) *CounterByStatusXX

CountedByStatusXX returns an http.Handler that passes requests to an underlying http.Handler and then counts the response by the first digit of its HTTP status code via go-metrics.

func (*CounterByStatusXX) ServeHTTP

func (c *CounterByStatusXX) ServeHTTP(w0 http.ResponseWriter, r *http.Request)

ServeHTTP passes the request to the underlying http.Handler and then counts the response by its HTTP status code via go-metrics.

type ESXHealthCheck

type ESXHealthCheck struct {
	// contains filtered or unexported fields
}

ESXHealthCheck will manage the health checks and manage a server's load balanacer status. On Stop, it will block until all LBs have received a 'bad' status.

func NewESXHealthCheck

func NewESXHealthCheck() *ESXHealthCheck

NewESXHealthCheck returns a new instance of ESXHealthCheck.

func (*ESXHealthCheck) Path

func (e *ESXHealthCheck) Path() string

Path returns the default ESX health path.

func (*ESXHealthCheck) ServeHTTP

func (e *ESXHealthCheck) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP will handle the health check requests on the server. ESXHealthCheck will return with an "ok" status as long as the ready flag is set to True. If a `deployer` query parameter is included, the request will not be counted as a load balancer.

func (*ESXHealthCheck) Start

func (e *ESXHealthCheck) Start(monitor *ActivityMonitor) error

Start will set the monitor and flip the ready flag to 'True'.

func (*ESXHealthCheck) Stop

func (e *ESXHealthCheck) Stop() error

Stop will set the flip the 'ready' flag and wait block until the server has removed itself from all load balancers.

type HealthCheckHandler

type HealthCheckHandler interface {
	http.Handler
	Path() string
	Start(*ActivityMonitor) error
	Stop() error
}

HealthCheckHandler is an interface used by SimpleServer and RPCServer to allow users to customize their service's health check. Start will be called just before server start up and the given ActivityMonitor should offer insite to the # of requests in flight, if needed. Stop will be called once the servers receive a kill signal.

func NewHealthCheckHandler

func NewHealthCheckHandler(cfg *config.Server) HealthCheckHandler

NewHealthCheckHandler will inspect the config to generate the appropriate HealthCheckHandler.

func RegisterHealthHandler

func RegisterHealthHandler(cfg *config.Server, monitor *ActivityMonitor, mx *mux.Router) HealthCheckHandler

RegisterHealthHandler will create a new HealthCheckHandler from the given config and add a handler to the given router.

type JSONEndpoint

type JSONEndpoint func(*http.Request) (int, interface{}, error)

JSONEndpoint is the JSONService equivalent to SimpleService's http.HandlerFunc.

type JSONService

type JSONService interface {
	Service

	// route - method - func
	JSONEndpoints() map[string]map[string]JSONEndpoint
	JSONMiddleware(JSONEndpoint) JSONEndpoint
}

JSONService is an interface defining a service that is made up of JSONEndpoints.

type MixedService

type MixedService interface {
	Service

	// route - method - func
	Endpoints() map[string]map[string]http.HandlerFunc

	// route - method - func
	JSONEndpoints() map[string]map[string]JSONEndpoint
	JSONMiddleware(JSONEndpoint) JSONEndpoint
}

MixedService is an interface defining service that offer JSONEndpoints and simple http.HandlerFunc endpoints.

type RPCServer

type RPCServer struct {
	// contains filtered or unexported fields
}

RPCServer is an experimental server that serves a gRPC server on one port and the same endpoints via JSON on another port.

func NewRPCServer

func NewRPCServer(cfg *config.Server) *RPCServer

NewRPCServer will instantiate a new experimental RPCServer with the given config.

func (*RPCServer) Register

func (r *RPCServer) Register(svc Service) error

Register will attempt to register the given RPCService with the server. If any other types are passed, Register will panic.

func (*RPCServer) ServeHTTP

func (r *RPCServer) ServeHTTP(w http.ResponseWriter, req *http.Request)

ServeHTTP is RPCServer's hook for metrics and safely executing each request.

func (*RPCServer) Start

func (r *RPCServer) Start() error

Start start the RPC server.

func (*RPCServer) Stop

func (r *RPCServer) Stop() error

Stop will signal the RPC server to stop and block until it does.

type RPCService

type RPCService interface {
	Service

	Service() (*grpc.ServiceDesc, interface{})

	// route - method - func
	JSONEndpoints() map[string]map[string]JSONEndpoint
	JSONMiddleware(JSONEndpoint) JSONEndpoint
}

RPCService is an interface defining an grpc-compatible service that offers JSONEndpoints.

type Server

type Server interface {
	Register(Service) error
	Start() error
	Stop() error
}

Server is the basic interface that defines what to expect from any server.

func NewServer

func NewServer(cfg *config.Server) Server

NewServer will inspect the config and generate the appropriate Server implementation.

type Service

type Service interface {
	Prefix() string

	// Middleware is a hook to enable services to add
	// any additional middleware.
	Middleware(http.Handler) http.Handler
}

Service is the most basic interface of a service that can be received and hosted by a Server.

type SimpleHealthCheck

type SimpleHealthCheck struct {
	// contains filtered or unexported fields
}

SimpleHealthCheck is a basic HealthCheckHandler implementation that _always_ returns with an "ok" status and shuts down immediately.

func NewSimpleHealthCheck

func NewSimpleHealthCheck(path string) *SimpleHealthCheck

NewSimpleHealthCheck will return a new SimpleHealthCheck instance.

func (*SimpleHealthCheck) Path

func (s *SimpleHealthCheck) Path() string

Path will return the configured status path to server on.

func (*SimpleHealthCheck) ServeHTTP

func (s *SimpleHealthCheck) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP will always respond with "ok-"+server.Name.

func (*SimpleHealthCheck) Start

func (s *SimpleHealthCheck) Start(monitor *ActivityMonitor) error

Start will do nothing.

func (*SimpleHealthCheck) Stop

func (s *SimpleHealthCheck) Stop() error

Stop will do nothing and return nil.

type SimpleServer

type SimpleServer struct {
	// contains filtered or unexported fields
}

SimpleServer is a basic http Server implementation for serving SimpleService, JSONService or MixedService implementations.

func NewSimpleServer

func NewSimpleServer(cfg *config.Server) *SimpleServer

NewSimpleServer will init the mux, exit channel and build the address from the given port. It will register the HealthCheckHandler at the given path and set up the shutDownHandler to be called on Stop().

func (*SimpleServer) Register

func (s *SimpleServer) Register(svcI Service) error

Register will accept and register SimpleServer, JSONService or MixedService implementations.

func (*SimpleServer) ServeHTTP

func (s *SimpleServer) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP is SimpleServer's hook for metrics and safely executing each request.

func (*SimpleServer) Start

func (s *SimpleServer) Start() error

Start will start the SimpleServer at it's configured address. If they are configured, this will start emitting metrics to Graphite, register profiling, health checks and access logging.

func (*SimpleServer) Stop

func (s *SimpleServer) Stop() error

Stop initiates the shutdown process and returns when the server completes.

type SimpleService

type SimpleService interface {
	Service

	// route - method - func
	Endpoints() map[string]map[string]http.HandlerFunc
}

SimpleService is an interface defining a service that is made up of http.HandlerFuncs.

type TCPKeepAliveListener

type TCPKeepAliveListener struct {
	*net.TCPListener
}

TCPKeepAliveListener sets TCP keep-alive timeouts on accepted connections. It's used by ListenAndServe and ListenAndServeTLS so dead TCP connections (e.g. closing laptop mid-download) eventually go away.

This is here because it is not exposed in the stdlib and we'd prefer to have a hold of the http.Server's net.Listener so we can close it on shutdown.

Taken from here: https://golang.org/src/net/http/server.go?s=63121:63175#L2120

func (TCPKeepAliveListener) Accept

func (ln TCPKeepAliveListener) Accept() (c net.Conn, err error)

Accept accepts the next incoming call and returns the new connection. KeepAlivePeriod is set properly.

type Timer

type Timer struct {
	metrics.Timer
	// contains filtered or unexported fields
}

Timer is an http.Handler that counts requests via go-metrics.

func Timed

func Timed(handler http.Handler, name string, registry metrics.Registry) *Timer

Timed returns an http.Handler that starts a timer, passes requests to an underlying http.Handler, stops the timer, and updates the timer via go-metrics.

func (*Timer) ServeHTTP

func (t *Timer) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP starts a timer, passes the request to the underlying http.Handler, stops the timer, and updates the timer via go-metrics.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL