bhttp

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Aug 16, 2024 License: MIT Imports: 9 Imported by: 1

README

bhttp

Pragmatic utilities for better http handlers in Go. Typed context, url reversing and error returns for Go http handlers

features

  • type-safe and modular context.Context for http handlers
  • reversing of http route patterns
  • return errors from handlers, and allow middleware to handle them
  • benchmark seem to suggest it also reduces alloc/op but i might be doing something wrong with the benchmarks

Downsides

  • the http.Request's context should not be used in the handler
  • about 2 extra allocations per request
  • quiet a lot of type parameters will pop-up, this decreases readability

Documentation

Overview

Package bhttp provides utilities for creating http handlers with buffered responses.

Index

Constants

This section is empty.

Variables

View Source
var ErrBufferFull = errors.New("buffer is full")

ErrBufferFull is returned when the write call will cause the buffer to be filled beyond its limit.

Functions

func ChainStd

func ChainStd(h http.Handler, m ...StdMiddleware) http.Handler

ChainStd turns a slice of standard middleware into wrapped calls. The left-most middleware will become the outer middleware. 'h' will be come the inner handler.

func Serve

func Serve[C context.Context](
	hdlr Handler[C], initCtx ContextInitFunc[C], os ...Option,
) http.Handler

Serve takes a handler with a customizable context that is able to return an error. To support this the response is buffered until the handler is done. If an error occurs the buffer is discarded and a full replacement response can be formulated. The underlying buffer is re-used between requests for improved performance.

func ServeFunc

func ServeFunc[C context.Context](
	hdlr HandlerFunc[C], initCtx ContextInitFunc[C], os ...Option,
) http.Handler

ServeFunc takes a handler func and then calls Serve.

Types

type ContextInitFunc added in v0.2.0

type ContextInitFunc[C context.Context] func(r *http.Request) C

ContextInitFunc describes the signature for a function to initialize the typed context.

type Handler

type Handler[C context.Context] interface {
	ServeBHTTP(ctx C, w ResponseWriter, r *http.Request) error
}

Handler mirrors http.Handler but it supports typed context values and a buffered response allow returning error.

func Chain

func Chain[C context.Context](h Handler[C], m ...Middleware[C]) Handler[C]

Chain takes the inner handler h and wraps it with middleware. The order is that of the Gorilla and Chi router. That is: the middleware provided first is called first and is the "outer" most wrapping, the middleware provided last will be the "inner most" wrapping (closest to the handler).

type HandlerFunc

type HandlerFunc[C context.Context] func(C, ResponseWriter, *http.Request) error

HandlerFunc allow casting a function to imple Handler.

func (HandlerFunc[C]) ServeBHTTP

func (f HandlerFunc[C]) ServeBHTTP(ctx C, w ResponseWriter, r *http.Request) error

ServeBHTTP implements the Handler interface.

type Logger

type Logger interface {
	LogUnhandledServeError(err error)
	LogImplicitFlushError(err error)
}

Logger can be implemented to get informed about important states.

type Middleware

type Middleware[C context.Context] func(Handler[C]) Handler[C]

Middleware functions wrap each other to create unilateral functionality.

type Option

type Option func(*opts)

Option allows for customization of the (buffered) handling logic.

func WithBufferLimit

func WithBufferLimit(v int) Option

WithBufferLimit allows limiting the buffered writer (if it buffered). This can protect against buffered response writers taking up too much memory per response.

func WithErrorLog

func WithErrorLog(v Logger) Option

WithErrorLog will add a standard library logger to allow observing some failure situations. If not specified it will log to log.Default().

type ResponseBuffer

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

ResponseBuffer is a http.ResponseWriter implementation that buffers writes up to configurable amount of bytes. This allows the implementation of handlers that can error halfway and return a completely different response instead of what was written before the error occurred.

func NewBufferResponse

func NewBufferResponse(resp http.ResponseWriter, limit int) *ResponseBuffer

NewBufferResponse inits a buffered response writer. It has a configurable limit after which the writing will return an error. This is to protect unchecked handlers from claiming too much memory. Limit can be set to -1 to disable this check.

func (*ResponseBuffer) FlushError

func (w *ResponseBuffer) FlushError() error

FlushError any buffered bytes to the underlying response writer and resets the buffer. After flush has been called the response data should be considered sent and in-transport to the client.

func (*ResponseBuffer) Free

func (w *ResponseBuffer) Free()

Free resets all members of the ResponseBuffer and puts it back in the sync pool to allow it to be re-used for a possible next initilization. It should be called after the handling has completed and the buffer should not be used after.

func (*ResponseBuffer) Header

func (w *ResponseBuffer) Header() http.Header

Header allows users to modify the headers (and trailers) sent to the client. The headers are not actually flushed to the underlying writer until a write or flush is being triggered.

func (*ResponseBuffer) ImplicitFlush

func (w *ResponseBuffer) ImplicitFlush() error

ImplicitFlush flushes data to the underlying writer without calling .Flush on it by proxy. This is provided separately from FlushError to allow for emulating the original ResponseWriter behaviour more correctly.

func (*ResponseBuffer) Reset

func (w *ResponseBuffer) Reset()

Reset provides the differentiating feature from a regular ResponseWriter: it allows changing the response completely even if some data has been written already. This behaviour cannot be guaranteed if flush has been called explicitly so in that case it will panic.

func (*ResponseBuffer) Unwrap

func (w *ResponseBuffer) Unwrap() http.ResponseWriter

Unwrap returns the underlying response writer. This is expected by the http.ResponseController to allow it to call appropriate optional interface implementations.

func (*ResponseBuffer) Write

func (w *ResponseBuffer) Write(buf []byte) (int, error)

Write appends the contents of p to the buffered response, growing the internal buffer as needed. If the write will cause the buffer be larger then the configure limit it will return ErrBufferFull.

func (*ResponseBuffer) WriteHeader

func (w *ResponseBuffer) WriteHeader(statusCode int)

WriteHeader will cause headers to be flushed to the underlying writer while calling WriteHeader on the underlying writer with the given status code.

type ResponseWriter

type ResponseWriter interface {
	http.ResponseWriter
	Reset()
}

ResponseWriter implements the http.ResponseWriter but the underlying bytes are buffered. This allows middleware to reset the writer and formulate a completely new response.

type Reverser

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

Reverser keeps track of named patterns and allows building URLS.

func NewReverser

func NewReverser() *Reverser

NewReverser inits the reverser.

func (Reverser) Named

func (r Reverser) Named(name, s string) string

Named is a convenience method that panics if naming the pattern fails.

func (Reverser) NamedPattern

func (r Reverser) NamedPattern(name, s string) (string, error)

NamedPattern will parse 's' as a path pattern while returning it as well.

func (Reverser) Reverse

func (r Reverser) Reverse(name string, vals ...string) (string, error)

Reverse reverses the named pattern into a url.

type ServeMux

type ServeMux[C context.Context] struct {
	// contains filtered or unexported fields
}

ServeMux is an extension to the standard http.ServeMux. It supports handling requests with a buffered response for error returns, typed context values and named routes.

func NewServeMux

func NewServeMux[C context.Context](initCtx ContextInitFunc[C], opts ...Option) *ServeMux[C]

NewServeMux inits a mux.

func (*ServeMux[C]) BHandle

func (m *ServeMux[C]) BHandle(pattern string, handler Handler[C], name ...string)

BHandle will invoke 'handler' with a buffered response for the named route and pattern.

func (*ServeMux[C]) BHandleFunc

func (m *ServeMux[C]) BHandleFunc(pattern string, handler HandlerFunc[C], name ...string)

BHandleFunc will invoke a handler func with a buffered response.

func (*ServeMux[C]) BUse

func (m *ServeMux[C]) BUse(mw ...Middleware[C])

BUse will add a middleware ONLY for any buffered http handling, that is handlers setup using BHandle or BHandleFunc.

func (*ServeMux[C]) Handle

func (m *ServeMux[C]) Handle(pattern string, handler http.Handler, name ...string)

Handle will invoke 'handler' with an unbuffered response for the named route and pattern.

func (*ServeMux[C]) HandleFunc

func (m *ServeMux[C]) HandleFunc(pattern string, handler http.HandlerFunc, name ...string)

HandleFunc will invoke 'handler' with a unbuffered response for the named route and pattern.

func (*ServeMux[C]) Reverse

func (m *ServeMux[C]) Reverse(name string, vals ...string) (string, error)

Reverse a route with 'name' using values for each parameter.

func (ServeMux[C]) ServeHTTP

func (m ServeMux[C]) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP maxes the mux implement http.Handler.

func (*ServeMux[C]) Use

func (m *ServeMux[C]) Use(mw ...StdMiddleware)

Use will add a standard http middleware triggered for both buffered and unbuffered request handling.

type StdMiddleware

type StdMiddleware func(http.Handler) http.Handler

StdMiddleware describes the type for a middleware without buffered responses.

Directories

Path Synopsis
internal
example
Package example implements example middleware in an outside package.
Package example implements example middleware in an outside package.
Package main defines automation targets using Magefile
Package main defines automation targets using Magefile

Jump to

Keyboard shortcuts

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