Documentation
¶
Overview ¶
Package serverhttp provides an owned standard-library HTTP server runtime.
Index ¶
- Variables
- func Chain(handler http.Handler, middleware ...Middleware) (http.Handler, error)
- type ConfigError
- type Middleware
- type Option
- func WithBaseContext(base func(net.Listener) context.Context) Option
- func WithBodyLimit(limit int64) Option
- func WithConnContext(connection func(context.Context, net.Conn) context.Context) Option
- func WithCorrelation(factory *correlation.Factory, options httpcorrelation.Options) Option
- func WithIdleTimeout(timeout time.Duration) Option
- func WithIngressMiddleware(middleware ...Middleware) Option
- func WithMaxHeaderBytes(limit int) Option
- func WithMiddleware(middleware ...Middleware) Option
- func WithReadHeaderTimeout(timeout time.Duration) Option
- func WithReadTimeout(timeout time.Duration) Option
- func WithShutdownTimeout(timeout time.Duration) Option
- func WithWriteTimeout(timeout time.Duration) Option
- type RunError
- type ServeError
- type Server
- type StateError
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrInvalidConfig = errors.New("invalid HTTP server configuration")
ErrInvalidConfig identifies invalid HTTP runtime configuration.
var ErrInvalidState = errors.New("invalid HTTP server state")
ErrInvalidState identifies an HTTP runtime operation rejected by its state.
Functions ¶
func Chain ¶
Chain composes middleware around handler in listed order.
Example ¶
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/faustbrian/go-correlation"
httpcorrelation "github.com/faustbrian/go-correlation/http"
"github.com/faustbrian/go-service/serverhttp"
)
func main() {
factory, err := correlation.NewFactory(correlation.FactoryOptions{})
if err != nil {
panic(err)
}
identity, err := httpcorrelation.New(factory, httpcorrelation.Options{})
if err != nil {
panic(err)
}
handler, err := serverhttp.Chain(
http.HandlerFunc(func(_ http.ResponseWriter, request *http.Request) {
values, _ := correlation.FromContext(request.Context())
fmt.Println(values.RequestID != "")
}),
serverhttp.Recover(),
identity.Wrap,
)
if err != nil {
panic(err)
}
handler.ServeHTTP(
httptest.NewRecorder(),
httptest.NewRequest(http.MethodGet, "/", nil),
)
}
Output: true
Example (AuthenticationAndAuthorization) ¶
package main
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"github.com/faustbrian/go-service/serverhttp"
)
type principalKey struct{}
func main() {
authentication := serverhttp.Middleware(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
fmt.Println("authenticate")
if request.Header.Get("Authorization") != "Bearer example" {
http.Error(writer, "unauthorized", http.StatusUnauthorized)
return
}
ctx := context.WithValue(request.Context(), principalKey{}, "user-1")
next.ServeHTTP(writer, request.WithContext(ctx))
})
})
authorization := serverhttp.Middleware(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
fmt.Println("authorize")
if request.Context().Value(principalKey{}) == nil {
http.Error(writer, "forbidden", http.StatusForbidden)
return
}
next.ServeHTTP(writer, request)
})
})
handler, err := serverhttp.Chain(
http.HandlerFunc(func(writer http.ResponseWriter, _ *http.Request) {
writer.WriteHeader(http.StatusNoContent)
}),
authentication,
authorization,
)
if err != nil {
panic(err)
}
request := httptest.NewRequest(http.MethodGet, "/", nil)
request.Header.Set("Authorization", "Bearer example")
recorder := httptest.NewRecorder()
handler.ServeHTTP(recorder, request)
fmt.Println(recorder.Code)
}
Output: authenticate authorize 204
Types ¶
type ConfigError ¶
type ConfigError struct {
// Field identifies the rejected configuration path.
Field string
// Reason describes why Field was rejected.
Reason string
}
ConfigError identifies one invalid HTTP runtime field.
func (*ConfigError) Unwrap ¶
func (err *ConfigError) Unwrap() error
Unwrap makes ConfigError inspectable with errors.Is.
type Middleware ¶
Middleware wraps an http.Handler. In Chain, the first middleware is the outermost and observes the request first and response last.
func LimitBody ¶
func LimitBody(limit int64) (Middleware, error)
LimitBody rejects a known oversized request before the handler and limits streaming or chunked bodies before their first read. Zero disables it.
func Recover ¶
func Recover() Middleware
Recover contains handler panics. If no response was committed, it removes prepared headers and sends a generic HTTP 500 response.
type Option ¶
type Option func(*config) error
Option configures a Server. A nil Option is invalid.
func WithBaseContext ¶
WithBaseContext sets the base context for accepted connections. The callback must return a non-nil context.
func WithBodyLimit ¶
WithBodyLimit configures the maximum request body size. Zero disables the limit.
func WithConnContext ¶
WithConnContext derives a context for each accepted connection. The callback must return a non-nil context.
func WithCorrelation ¶
func WithCorrelation( factory *correlation.Factory, options httpcorrelation.Options, ) Option
WithCorrelation installs correlation-owned HTTP identity immediately after panic recovery and before ingress middleware or body limits.
func WithIdleTimeout ¶
WithIdleTimeout configures the keep-alive idle timeout. Zero disables it.
func WithIngressMiddleware ¶
func WithIngressMiddleware(middleware ...Middleware) Option
WithIngressMiddleware appends middleware after request identity and before request body limits.
func WithMaxHeaderBytes ¶
WithMaxHeaderBytes configures the maximum request-header size.
func WithMiddleware ¶
func WithMiddleware(middleware ...Middleware) Option
WithMiddleware appends user middleware in visible listed order.
func WithReadHeaderTimeout ¶
WithReadHeaderTimeout configures the request-header read timeout. Zero disables it.
func WithReadTimeout ¶
WithReadTimeout configures the full request read timeout. Zero disables it.
func WithShutdownTimeout ¶
WithShutdownTimeout configures the graceful-shutdown bound. Zero is invalid because Run always owns a finite shutdown bound.
func WithWriteTimeout ¶
WithWriteTimeout configures the response write timeout. Zero disables it.
type RunError ¶
type RunError struct {
// Failures contains graceful-shutdown and forced-close failures.
Failures []error
}
RunError aggregates failures observed while stopping an HTTP server.
type ServeError ¶
type ServeError struct {
// Err is the unexpected listener or serving failure.
Err error
}
ServeError reports an unexpected listener or serving failure.
func (*ServeError) Unwrap ¶
func (err *ServeError) Unwrap() error
Unwrap returns the serving failure.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server owns one listener and its standard-library HTTP server.
func New ¶
New constructs a server without accepting connections or starting goroutines. Ownership of listener transfers to Server after success.
func (*Server) Close ¶
Close releases the owned listener before Run or force-closes an active server. Concurrent and repeated calls return the same result. A closed server cannot be run.
func (*Server) HTTPServer ¶
HTTPServer returns the configured server. Callers must not mutate it after Run begins.
type StateError ¶
type StateError struct {
// Operation is the rejected runtime operation.
Operation string
// State describes the runtime state in which Operation was rejected.
State string
}
StateError reports an invalid HTTP runtime operation.
func (*StateError) Unwrap ¶
func (err *StateError) Unwrap() error
Unwrap makes StateError inspectable with errors.Is.