Documentation
¶
Overview ¶
package fxhttp provides a convenient way to create well behaved http servers
Example ¶
package main
import (
"bytes"
"context"
"fmt"
"io"
"net/http"
sconfig "github.com/exoscale/stelling/config"
"github.com/exoscale/stelling/fxhttp"
"go.uber.org/fx"
"go.uber.org/fx/fxevent"
"go.uber.org/zap"
)
type Config struct {
fxhttp.Server
}
func main() {
conf := &Config{}
args := []string{"http-test"}
if err := sconfig.Load(conf, args); err != nil {
panic(err)
}
opts := fx.Options(
// Suppressing fx logs to ensure deterministic output
fx.WithLogger(func() fxevent.Logger { return fxevent.NopLogger }),
fxhttp.NewModule(conf),
fx.Provide(
// supplying a NopLogger to make output deterministic
// In practise you'd use fxlogging.NewModule to get a zap logger
// and replace the fxevent logger
zap.NewNop,
newMux,
),
// We explicitly need to invoke this, because ordering matters
fx.Invoke(fxhttp.StartHttpServer),
fx.Invoke(run),
)
if err := fx.ValidateApp(opts); err != nil {
panic(err)
}
fx.New(opts).Run()
}
func newMux() http.Handler {
// You probably want to request a slice of routes here
// So you can set them on the mux
mux := http.NewServeMux()
mux.HandleFunc("/foo", func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte("Hello Stelling"))
})
return mux
}
func run(lc fx.Lifecycle, sd fx.Shutdowner) {
lc.Append(fx.Hook{
OnStart: func(ctx context.Context) error {
go func() {
resp, err := http.DefaultClient.Get("http://localhost:8080/foo") //nolint:noctx
if err != nil {
panic(err)
}
fmt.Println("Response code for GET http://localhost:8080/foo", resp.StatusCode)
body := resp.Body
data, err := io.ReadAll(body)
if err != nil {
panic(err)
}
hasData := bytes.Equal(data, []byte("Hello Stelling"))
fmt.Println("Endpoint returned correct data", hasData)
defer body.Close()
sd.Shutdown() //nolint:errcheck
}()
return nil
},
})
}
Output: Response code for GET http://localhost:8080/foo 200 Endpoint returned correct data true
Index ¶
- func GetCertReloaderConfig(conf ServerConfig) *reloader.CertReloaderConfig
- func NamedSocketListener(name string) (net.Listener, error)
- func NewHTTPServer(lc fx.Lifecycle, conf ServerConfig, r *reloader.CertReloader, ...) (*http.Server, error)
- func NewListener(ctx context.Context, socketName string, addr string) (net.Listener, error)
- func NewModule(conf ServerConfig, sOpts ...serverModuleOption) fx.Option
- func NewNamedModule(name string, conf ServerConfig) fx.Optiondeprecated
- func RPCMethodFromContext(ctx context.Context) string
- func StartHttpServer(lc fx.Lifecycle, s *server, logger *zap.Logger)
- func WithRPCMethodMapper(mapper func(*http.Request) string) serverModuleOption
- func WithServerModuleName(name string) serverModuleOption
- type Middleware
- type RPCMethodMapper
- type Server
- type ServerConfig
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GetCertReloaderConfig ¶
func GetCertReloaderConfig(conf ServerConfig) *reloader.CertReloaderConfig
func NamedSocketListener ¶
caches the systemd-activated fds and their names Returns the listener associated with the arg
func NewHTTPServer ¶
func NewHTTPServer(lc fx.Lifecycle, conf ServerConfig, r *reloader.CertReloader, handler http.Handler, middleware []*Middleware) (*http.Server, error)
func NewListener ¶
func NewModule ¶
func NewModule(conf ServerConfig, sOpts ...serverModuleOption) fx.Option
NewModule provides a configured *http.Server to the system You still have to invoke StartHttpServer to ensure it starts
func NewNamedModule
deprecated
func NewNamedModule(name string, conf ServerConfig) fx.Option
NewNamedModule adds a named http server to the system It is mostly of use for other stelling components which may need to start their own http servers The average application should be able to use NewModule instead
Deprecated: please use NewModule with the WithServerModuleName option and add `fx.Invoke(fx.Annotate(StartHttpServer), fx.ParamTags("", "name=\"yourname\"", ""))` to the system
func RPCMethodFromContext ¶
RPCMethodFromContext returns the current rpc.method stored in the context Returns the empty string if not present
func WithRPCMethodMapper ¶
WithRPCMethodMapper adds a function that maps request to the name of the rpc.method This information is used by various observability modules to annotate the data
func WithServerModuleName ¶
func WithServerModuleName(name string) serverModuleOption
WithServerModuleName will annotate the outputs with the given name
Types ¶
type Middleware ¶
func NewInjectRPCMethodMiddleware ¶
func NewInjectRPCMethodMiddleware(mapper RPCMethodMapper) *Middleware
type RPCMethodMapper ¶
RPCMethodMapper returns a fully qualified rpc method name for a given http request
type Server ¶
type Server struct {
// A systemd socket name. Takes precedence over Address
// In order to simplify, only systemd-activated socket with names are allowed, even if it is
// just one socket
SocketName string
// Address is the address+port the server will bind to, as passed to net.Listen
// If the Address starts with a / we will create unix domainsocket listener
Address string `default:"localhost:8080" validate:"tcp_addr|unix_addr"`
// TLS indicates whether the http server exposes with TLS
TLS bool
// CertFile is the path to the pem encoded TLS certificate
CertFile string `validate:"required_if=TLS true,omitempty,file"`
// KeyFile is the path to the pem encoded private key of the TLS certificate
KeyFile string `validate:"required_if=TLS true,omitempty,file"`
// ClientCAFile is the path to a pem encoded CA cert bundle used to validate clients
ClientCAFile string `validate:"excluded_without=TLS,omitempty,file"`
}
func (*Server) HttpServerConfig ¶
func (*Server) MarshalLogObject ¶
func (s *Server) MarshalLogObject(enc zapcore.ObjectEncoder) error
type ServerConfig ¶
type ServerConfig interface {
HttpServerConfig() *Server
}