fxhttp

package
v0.0.0-...-edc4474 Latest Latest
Warning

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

Go to latest
Published: May 5, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

README

HTTP Module

This module provides http server support.

This package provides 2 modules:

  • A regular module which provides a top level http server The other stelling modules will add various middleware to this server
  • A "named" module, which provides a named submodule: this one is intended to be used in other stelling packages, such as metrics. It doesn't provide all the features of the main module. To create the main http server of your application you should use the regular module.

Components

The module lazily provides the following components:

  • A *http.Server

You must supply a single http.Handler in the system, which will be set as the servers handler. This way, the module does not enforce any opinions on how the server mux is constructed.

The client Invokes StartHttpServer explicitly in his system. This allows fine grained control over the start and stop order of components that do not share a dependency.

The module will also use CertficateReloader in case the configuration specifies TLS options.

Options

  • WithRPCMethodMapper Passes in a function which returns the name of the rpc method a particular request is calling. This information will be added as metadata to the observability
  • WithServerModuleName This option allows creating additional "named" http servers. It is intended to be used by other stelling modules, such as the metrics. Named servers do not provide all the features of the main server: for example no middleware will be installed.j

Configuration

The module provides the following configuration options:

  • Address: The address + port, or a unix filepath, on which the http server will bind
  • TLS: A boolean indicating that the server must expose using TLS
  • CertFile: Path to the pem encoded server TLS certificate
  • KeyFile: Path to the pem encoded private key of the server TLS certificate
  • ClientCAFile: Path to a pem encoded CA cert bundle used to validate clients. No client validation happens if unset.

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

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetCertReloaderConfig

func GetCertReloaderConfig(conf ServerConfig) *reloader.CertReloaderConfig

func NamedSocketListener

func NamedSocketListener(name string) (net.Listener, error)

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 NewListener(ctx context.Context, socketName string, addr string) (net.Listener, error)

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

func RPCMethodFromContext(ctx context.Context) string

RPCMethodFromContext returns the current rpc.method stored in the context Returns the empty string if not present

func StartHttpServer

func StartHttpServer(lc fx.Lifecycle, s *server, logger *zap.Logger)

func WithRPCMethodMapper

func WithRPCMethodMapper(mapper func(*http.Request) string) serverModuleOption

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

type Middleware struct {
	Handler func(http.Handler) http.Handler
	Weight  int
}

func NewInjectRPCMethodMiddleware

func NewInjectRPCMethodMiddleware(mapper RPCMethodMapper) *Middleware

type RPCMethodMapper

type RPCMethodMapper func(req *http.Request) string

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 (s *Server) HttpServerConfig() *Server

func (*Server) MarshalLogObject

func (s *Server) MarshalLogObject(enc zapcore.ObjectEncoder) error

type ServerConfig

type ServerConfig interface {
	HttpServerConfig() *Server
}

Jump to

Keyboard shortcuts

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