serv

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Apr 25, 2024 License: BSD-3-Clause Imports: 16 Imported by: 2

README

serv

Latest release Build status Go Report Card Documentation

Package serv contains a server implementation based on http.Server, with sane and safe defaults.


go get github.com/go-pogo/serv
import "github.com/go-pogo/serv"

Documentation

Additional detailed documentation is available at pkg.go.dev

Created with

License

Copyright © 2021-2024 Roel Schut. All rights reserved.

This project is governed by a BSD-style license that can be found in the LICENSE file.

Documentation

Index

Examples

Constants

View Source
const (
	ErrMissingPort   errors.Msg = "missing port"
	ErrInvalidFormat errors.Msg = "invalid format"
)
View Source
const (
	ErrAlreadyStarted   errors.Msg = "server has already started"
	ErrUnableToStart    errors.Msg = "unable to start server"
	ErrUnableToShutdown errors.Msg = "unable to shutdown server"
	ErrUnableToClose    errors.Msg = "unable to close server"

	ShutdownError errors.Kind = "shutdown error"
	CloseError    errors.Kind = "close error"
)
View Source
const ErrAppendRootCAFailure errors.Msg = "failed to append certificate to root ca pool"
View Source
const ErrHandlerIsNoRouteHandler errors.Msg = "server handler is not a RouteHandler"

Variables

This section is empty.

Functions

func AddHandlerName added in v0.2.0

func AddHandlerName(name string, next http.Handler) http.Handler

AddHandlerName adds name as value to the request's context. It should be used on a per route/handler basis. The handler's name can be retrieved using HandlerName.

func AddServerName added in v0.2.0

func AddServerName(name string, next http.Handler) http.Handler

AddServerName adds the server's name to the request's context. This is done automatically when a name is set using WithName. The server's name can be retrieved using ServerName.

func BaseContext

func BaseContext(ctx context.Context) func(_ net.Listener) context.Context

BaseContext returns a function which returns the provided context.

func DefaultTLSConfig

func DefaultTLSConfig() *tls.Config

DefaultTLSConfig returns a modern preconfigured tls.Config.

func GetCertificate added in v0.2.0

func GetCertificate(cl CertificateLoader) func(*tls.ClientHelloInfo) (*tls.Certificate, error)

GetCertificate can be used in tls.Config to load a certificate when it's requested for.

func HandlerName added in v0.2.0

func HandlerName(ctx context.Context) string

HandlerName gets the handler's name from the context values. Its returned value may be an empty string.

func JoinHostPort

func JoinHostPort(host string, port Port) string

JoinHostPort uses net.JoinHostPort to combine host and port into a network address of the form "host:port". If host contains a colon, as found in literal IPv6 addresses, then JoinHostPort returns "[host]:port".

func RegisterRoutes added in v0.2.0

func RegisterRoutes(rh RouteHandler, routes ...Route)

RegisterRoutes registers [Route]s to a RouteHandler.

func ServerName

func ServerName(ctx context.Context) string

ServerName gets the server's name from context values. Its return value may be an empty string.

func WriteJSON added in v0.2.0

func WriteJSON(w http.ResponseWriter, v any) error

WriteJSON encodes v to JSON and writes it to w.

func WriteJSONError added in v0.2.0

func WriteJSONError(w http.ResponseWriter, err error) error

WriteJSONError encodes error err to JSON and writes it to w.

Types

type CertificateLoader

type CertificateLoader interface {
	LoadCertificate() (*tls.Certificate, error)
}

CertificateLoader loads a tls.Certificate from any source.

type Config

type Config struct {
	// ReadTimeout is the maximum duration for reading the entire request,
	// including the body.
	// See [http.Server.ReadTimeout] for additional information.
	ReadTimeout time.Duration `default:"5s"`
	// ReadHeaderTimeout is the amount of time allowed to read request headers.
	// See [http.Server.ReadHeaderTimeout] for additional information.
	ReadHeaderTimeout time.Duration `default:"2s"`
	// WriteTimeout is the maximum duration before timing out writes of the
	// response.
	// See [http.Server.WriteTimeout] for additional information.
	WriteTimeout time.Duration `default:"10s"`
	// IdleTimeout is the maximum amount of time to wait for the next request
	// when keep-alives are enabled.
	// See [http.Server.IdleTimeout] for additional information.
	IdleTimeout time.Duration `default:"120s"`
	// ShutdownTimeout is the default maximum duration for shutting down the
	// [Server] and waiting for all connections to be closed.
	ShutdownTimeout time.Duration `default:"60s"`
	// MaxHeaderBytes controls the maximum number of bytes the server will read
	// parsing the [http.Request] header's keys and values, including the
	// request line. It does not limit the size of the request body.
	// See [http.Server.MaxHeaderBytes] for additional information.
	MaxHeaderBytes uint64 `default:"10240"` // data.Bytes => 10 KiB
}

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns a Config with safe default values.

func (*Config) ApplyTo

func (cfg *Config) ApplyTo(s *http.Server)

ApplyTo applies the Config fields' values to http.Server s.

func (*Config) Default

func (cfg *Config) Default()

Default sets any zero values on Config to a default non-zero value similar to DefaultConfig.

func (*Config) IsZero added in v0.2.0

func (cfg *Config) IsZero() bool

IsZero indicates Config equals its zero value.

type ErrorLoggerProvider added in v0.2.0

type ErrorLoggerProvider interface {
	ErrorLogger() *log.Logger
}

type InvalidStateError added in v0.2.0

type InvalidStateError struct {
	Err   error
	State State
}

InvalidStateError is returned when an operation is attempted on a Server that is in an invalid state for that operation to succeed.

func (InvalidStateError) Error added in v0.2.0

func (u InvalidStateError) Error() string

func (InvalidStateError) Unwrap added in v0.2.0

func (u InvalidStateError) Unwrap() error

type Logger

type Logger interface {
	ServerStart(name, addr string)
	ServerShutdown(name string)
	ServerClose(name string)
}

Logger logs a Server's lifecycle events.

func DefaultLogger

func DefaultLogger(l *log.Logger) Logger

DefaultLogger returns a Logger that uses a log.Logger to log the Server's lifecycle events. It defaults to log.Default if the provided log.Logger l is nil.

func NopLogger

func NopLogger() Logger

NopLogger returns a Logger that does nothing.

type Option

type Option interface {
	// contains filtered or unexported methods
}

func WithBaseContext added in v0.2.0

func WithBaseContext(ctx context.Context) Option

WithBaseContext sets the provided context.Context ctx to the Server's internal http.Server.BaseContext.

func WithDefaultLogger added in v0.2.0

func WithDefaultLogger() Option

WithDefaultLogger adds a DefaultLogger to the Server.

func WithDefaultTLSConfig added in v0.2.0

func WithDefaultTLSConfig(opts ...TLSOption) Option

WithDefaultTLSConfig sets the Server's internal http.Server.TLSConfig to the value of DefaultTLSConfig. Any provided TLSOption(s) will be applied to this tls.Config.

func WithErrorLogger added in v0.2.0

func WithErrorLogger(l *log.Logger) Option

func WithHandler added in v0.2.0

func WithHandler(h http.Handler) Option

WithHandler sets the Server's [Server.Handler] to h.

func WithLogger

func WithLogger(l Logger) Option

WithLogger adds a Logger to the Server. It will also set the internal http.Server.ErrorLog if Logger l also implements ErrorLoggerProvider.

func WithName

func WithName(name string) Option

WithName adds the Server's name as value to the http.Request's context by wrapping the [Server.Handler] with AddServerName. This is done when the Server starts.

func WithOptions

func WithOptions(opts ...Option) Option

WithOptions wraps multiple options into a single Option.

func WithRoutesRegisterer added in v0.2.0

func WithRoutesRegisterer(reg ...RoutesRegisterer) Option

WithRoutesRegisterer uses the provided RoutesRegisterer(s) to add [Route]s to the Server's [Server.Handler]. It will use DefaultServeMux as handler when [Server.Handler] is nil. It returns an ErrHandlerIsNoRouteHandler error when [Server.Handler] is not a RouteHandler.

func WithTLS

func WithTLS(conf *tls.Config, opts ...TLSOption) Option

WithTLS sets the provided tls.Config to the Server's internal http.Server.TLSConfig. Any provided TLSOption(s) will be applied to this tls.Config.

type Port

type Port uint16

Port represents a network port.

func ParsePort

func ParsePort(s string) (Port, error)

ParsePort parses string s into a Port. A PortParseError containing a [PortParseError.Cause] is returned when an error is encountered.

Example
port, err := ParsePort(":8080")
if err != nil {
	log.Fatal(err)
}
fmt.Println(port)
Output:

8080

func SplitHostPort

func SplitHostPort(hostport string) (string, Port, error)

SplitHostPort uses net.SplitHostPort to split a network address of the form "host:port", "host%zone:port", "[host]:port" or "[host%zone]:port" into host or host%zone and Port. A PortParseError is returned when an error is encountered.

Example
host, port, err := SplitHostPort("localhost:8080")
if err != nil {
	log.Fatal(err)
}
fmt.Println(host, port)
Output:

localhost 8080

func (Port) Addr

func (p Port) Addr() string

Addr returns the port as an address string which can be used as value in [Server.Addr] or http.Server.Addr.

func (Port) MarshalText

func (p Port) MarshalText() ([]byte, error)

MarshalText marshals Port into a byte slice using Port.String. This method implements the encoding.TextMarshaler interface.

func (*Port) Set added in v0.2.0

func (p *Port) Set(s string) (err error)

Set parses string s into the Port using ParsePort. This method implements the flag.Value interface.

func (Port) String

func (p Port) String() string

String returns the port as a formatted string using strconv.FormatUint.

func (*Port) UnmarshalText

func (p *Port) UnmarshalText(text []byte) (err error)

UnmarshalText unmarshals text into Port using ParsePort. This method implements the encoding.TextUnmarshaler interface.

type PortParseError

type PortParseError struct {
	// Cause is the underlying error. It is never nil.
	Cause error
	// Input string that triggered the error
	Input string
}

func (*PortParseError) Error

func (p *PortParseError) Error() string

func (*PortParseError) Unwrap

func (p *PortParseError) Unwrap() error

type Route added in v0.2.0

type Route struct {
	// Name of the route.
	Name string
	// Method used to handle the route.
	Method string
	// Pattern to access the route.
	Pattern string
	// Handler is the [http.Handler] that handles the route.
	Handler http.Handler
}

Route is a http.Handler which represents a route that can be registered to a RouteHandler.

func (Route) ServeHTTP added in v0.2.0

func (r Route) ServeHTTP(wri http.ResponseWriter, req *http.Request)

type RouteHandler added in v0.2.0

type RouteHandler interface {
	HandleRoute(route Route)
}

RouteHandler handles routes.

type Router added in v0.2.0

type Router interface {
	RouteHandler
	http.Handler
}

Router is a http.Handler that can handle routes.

type RoutesRegisterer added in v0.2.0

type RoutesRegisterer interface {
	RegisterRoutes(rh RouteHandler)
}

RoutesRegisterer registers routes to a RouteHandler.

type RoutesRegistererFunc added in v0.2.0

type RoutesRegistererFunc func(rh RouteHandler)

RoutesRegistererFunc registers routes to a RouteHandler.

func (RoutesRegistererFunc) RegisterRoutes added in v0.2.0

func (fn RoutesRegistererFunc) RegisterRoutes(rh RouteHandler)

type ServeMux added in v0.2.0

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

ServeMux uses an internal embedded http.ServeMux to handle routes. It implements the Router interface on top of that. See http.ServeMux for additional information about pattern syntax, compatibility etc.

func DefaultServeMux added in v0.2.0

func DefaultServeMux() *ServeMux

DefaultServeMux returns a ServeMux containing http.DefaultServeMux.

func NewServeMux added in v0.2.0

func NewServeMux() *ServeMux

NewServeMux creates a new ServeMux and is ready to be used.

func (*ServeMux) HandleRoute added in v0.2.0

func (mux *ServeMux) HandleRoute(route Route)

HandleRoute registers a route to the ServeMux using its internal http.ServeMux.Handle.

func (*ServeMux) ServeHTTP added in v0.2.1

func (mux *ServeMux) ServeHTTP(wri http.ResponseWriter, req *http.Request)

func (*ServeMux) WithNotFoundHandler added in v0.2.1

func (mux *ServeMux) WithNotFoundHandler(h http.Handler) *ServeMux

WithNotFoundHandler sets a http.Handler which is called when there is no matching pattern. If not set, ServeMux will use the internal http.ServeMux's default not found handler, which is http.NotFound.

type Server

type Server struct {

	// Config to apply to the internal [http.Server], [DefaultConfig] if zero.
	// Changes to [Config] after starting the [Server] will not be applied
	// until after the [Server] is restarted.
	Config Config
	// Addr optionally specifies the TCP address for the server to listen on.
	// Changing Addr after starting the [Server] will not affect it until after
	// the [Server] is restarted.
	// See [net.Dial] for details of the address format.
	// See [http.Server] for additional information.
	Addr string
	// Handler to invoke, [DefaultServeMux] if nil. Changing Handler after the
	// [Server] has started will not have any effect until after the [Server]
	// is restarted.
	Handler http.Handler
	// contains filtered or unexported fields
}

Server is a wrapper for http.Server. The zero value is safe and ready to use, and will apply safe defaults on starting the Server.

func New

func New(opts ...Option) (*Server, error)

New creates a new Server with a default Config.

func (*Server) Close

func (srv *Server) Close() error

Close immediately closes all active net.Listener(s) and any connections in state http.StateNew, http.StateActive, or http.StateIdle. An InvalidStateError containing a ErrUnableToClose error is returned when the server is not started. For a graceful shutdown, use Server.Shutdown.

func (*Server) ListenAndServe

func (srv *Server) ListenAndServe() error

ListenAndServe is a wrapper for http.Server.ListenAndServe.

func (*Server) ListenAndServeTLS

func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error

ListenAndServeTLS is a wrapper for http.Server.ListenAndServeTLS.

func (*Server) Name

func (srv *Server) Name() string

Name returns an optional provided name of the server. Use WithName to set the server's name.

func (*Server) Run

func (srv *Server) Run() error

Run starts the server and calls either Server.ListenAndServe or Server.ListenAndServeTLS, depending on the provided TLS config/option(s). Unlike Server.Serve, Server.ListenAndServe, Server.ServeTLS, and Server.ListenAndServeTLS, Run will not return a http.ErrServerClosed error when the server is closed.

func (*Server) Serve

func (srv *Server) Serve(l net.Listener) error

Serve is a wrapper for http.Server.Serve.

func (*Server) ServeTLS

func (srv *Server) ServeTLS(l net.Listener, certFile, keyFile string) error

ServeTLS is a wrapper for http.Server.ServeTLS.

func (*Server) Shutdown

func (srv *Server) Shutdown(ctx context.Context) error

Shutdown gracefully shuts down the server without interrupting any active connections. Just like the underlying http.Server, Shutdown works by first closing all open listeners, then closing all idle connections, and then waiting indefinitely for connections to return to idle and then shut down. If [Config.ShutdownTimeout] is set and/or the provided context expires before the shutdown is complete, Shutdown returns the context's error. Otherwise, it returns any error returned from closing the Server's underlying net.Listener(s). An InvalidStateError containing a ErrUnableToShutdown error is returned when the server is not started.

func (*Server) State added in v0.2.0

func (srv *Server) State() State

State returns the current State of the Server.

func (*Server) With added in v0.2.0

func (srv *Server) With(opts ...Option) error

With applies additional option(s) to the server. It will return an InvalidStateError containing a ErrAlreadyStarted error when the server has already started.

type State added in v0.2.0

type State uint32
const (
	// StateUnstarted is the default state of a [Server] when it is created.
	StateUnstarted State = iota
	// StateStarted indicates the [Server] is (almost) ready to start listening
	// for incoming connections.
	StateStarted
	// StateErrored indicates the [Server] has encountered an error while
	// listening for incoming connections.
	StateErrored
	// StateClosing indicates the [Server] is in the process of closing and
	// does not accept any incoming connections.
	StateClosing
	// StateClosed indicates the [Server] has been completely closed and is no
	// longer listening for incoming connections.
	StateClosed
)

func (State) String added in v0.2.0

func (s State) String() string

type TLSConfig

type TLSConfig struct {
	// CACertFile is the path to the root certificate authority file. It is
	// used to verify the client's (whom connect to the server) certificate.
	CACertFile string `env:"" flag:"tls-ca"`
	// CertFile is the path to the server's certificate file.
	CertFile string `env:"" flag:"tls-cert"`
	// KeyFile is the path to the server's private key file.
	KeyFile string `env:"" flag:"tls-key"`

	// VerifyClient enables mutual tls authentication.
	VerifyClient bool `env:""`
	// InsecureSkipVerify disabled all certificate verification and should only
	// be used for testing. See [tls.Config.InsecureSkipVerify] for additional
	// information.
	InsecureSkipVerify bool `env:""`
}

func (TLSConfig) ApplyTo added in v0.2.0

func (tc TLSConfig) ApplyTo(conf *tls.Config) error

ApplyTo applies the TLSConfig fields' values to the provided tls.Config.

type TLSKeyPair

type TLSKeyPair struct {
	CertFile string
	KeyFile  string
}

TLSKeyPair contains the paths to a public/private key pair of files.

func (TLSKeyPair) ApplyTo added in v0.2.0

func (kp TLSKeyPair) ApplyTo(conf *tls.Config) error

ApplyTo adds the TLSKeyPair certificates to the provided tls.Config.

func (TLSKeyPair) LoadCertificate

func (kp TLSKeyPair) LoadCertificate() (*tls.Certificate, error)

LoadCertificate reads and parses the key pair files with tls.LoadX509KeyPair. The files must contain PEM encoded data.

type TLSOption

type TLSOption interface {
	ApplyTo(conf *tls.Config) error
}

type TLSPemBlocks

type TLSPemBlocks struct {
	Cert []byte
	Key  []byte
}

certPEMBlock, keyPEMBlock

func (TLSPemBlocks) ApplyTo added in v0.2.0

func (pb TLSPemBlocks) ApplyTo(conf *tls.Config) error

ApplyTo adds the TLSPemBlocks certificates to the provided tls.Config.

func (TLSPemBlocks) LoadCertificate

func (pb TLSPemBlocks) LoadCertificate() (*tls.Certificate, error)

LoadCertificate parses the [TLSPemBlocks.Cert] and [TLSPemBlocks.Key] blocks using tls.X509KeyPair. The []byte values must contain PEM encoded data.

Directories

Path Synopsis
_examples

Jump to

Keyboard shortcuts

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