Documentation
¶
Overview ¶
Package bhttp provides buffered HTTP response handling with context-first, error-returning handlers, named routes, and prefix mounting.
Overview ¶
bhttp extends the standard library's HTTP handling with four key features: error-returning handlers for clean error propagation, context as the first handler argument, named routes with URL reversing, and prefix-based mounting for composing handler trees. The buffered response writer is a necessary consequence—it allows the framework to discard partial output and generate clean error responses when handlers fail.
A minimal example:
mux := bhttp.NewServeMux()
mux.HandleFunc("GET /items/{id}", func(ctx context.Context, w bhttp.ResponseWriter, r *http.Request) error {
item, err := db.GetItem(r.PathValue("id"))
if err != nil {
return bhttp.NewError(bhttp.CodeNotFound, err)
}
return json.NewEncoder(w).Encode(item)
}, "get-item")
Handler Signature ¶
bhttp handlers differ from standard http.Handlers in three ways:
- Context is the first argument (not extracted from the request)
- They write to a ResponseWriter that buffers output
- They return an error that triggers automatic response handling
The handler signature is:
func(ctx context.Context, w bhttp.ResponseWriter, r *http.Request) error
Buffered Response Writer ¶
The ResponseWriter interface extends http.ResponseWriter with buffering. All writes are held in memory until explicitly flushed or until the handler returns successfully. This enables:
- Complete response replacement when errors occur mid-handler
- Headers modification after initial writes
- Clean error responses without partial content
Key methods:
- [ResponseWriter.Reset] clears the buffer and headers for a fresh response
- [ResponseWriter.FlushBuffer] writes buffered content to the underlying writer
- [ResponseWriter.Free] returns the buffer to a pool (called automatically by the mux)
Example of response replacement on error:
func handler(ctx context.Context, w bhttp.ResponseWriter, r *http.Request) error {
w.Header().Set("Content-Type", "application/json")
fmt.Fprintf(w, `{"status": "processing"`)
result, err := process()
if err != nil {
// Everything written so far is discarded
return bhttp.NewError(bhttp.CodeInternalServerError, err)
}
fmt.Fprintf(w, `, "result": %q}`, result)
return nil
}
Error Handling ¶
When a handler returns an error, the buffer is automatically reset and an appropriate HTTP error response is generated:
- *Error (created with NewError): Uses the error's code and message
- Other errors: Logged and converted to 500 Internal Server Error
Create errors with specific HTTP status codes using NewError:
return bhttp.NewError(bhttp.CodeBadRequest, errors.New("invalid input"))
return bhttp.NewError(bhttp.CodeNotFound, fmt.Errorf("user %s not found", id))
return bhttp.NewError(bhttp.CodeForbidden, errors.New("access denied"))
All standard HTTP 4xx and 5xx status codes are available as Code constants.
Middleware ¶
Middleware wraps handlers to add cross-cutting concerns. The Middleware type operates on BareHandler:
func loggingMiddleware(next bhttp.BareHandler) bhttp.BareHandler {
return bhttp.BareHandlerFunc(func(w bhttp.ResponseWriter, r *http.Request) error {
start := time.Now()
err := next.ServeBareBHTTP(w, r)
log.Printf("%s %s took %v", r.Method, r.URL.Path, time.Since(start))
return err
})
}
mux := bhttp.NewServeMux()
mux.Use(loggingMiddleware)
Middleware can inspect and transform errors, modify the request context, or reset and replace responses entirely.
Named Routes and URL Reversing ¶
Routes can be named for URL generation, avoiding hardcoded paths:
mux.HandleFunc("GET /users/{id}", getUser, "get-user")
mux.HandleFunc("POST /users", createUser, "create-user")
// Generate URLs by name
url, err := mux.Reverse("get-user", "123") // returns "/users/123"
The Reverser component parses standard library route patterns and substitutes path parameters in order.
Mounting ¶
Handlers can be mounted under a prefix using ServeMux.Mount, ServeMux.MountFunc, ServeMux.MountBare, or ServeMux.MountStd. The mounted handler receives requests with the mount prefix stripped from the path. Middleware registered via ServeMux.Use sees the original path; the strip happens after middleware runs.
mux.MountFunc("/api", func(ctx context.Context, w bhttp.ResponseWriter, r *http.Request) error {
// Request to /api/users arrives with r.URL.Path == "/users"
fmt.Fprintf(w, "api: %s", r.URL.Path)
return nil
})
// Mount a standard library http.Handler
mux.MountStd("/debug", http.DefaultServeMux)
Mount registers both the exact prefix and the subtree (e.g. /api and /api/) on the underlying http.ServeMux.
ServeMux ¶
ServeMux combines all components into a complete HTTP multiplexer that implements http.Handler:
- NewServeMux creates a mux with default settings
- NewServeMuxWith creates a mux with custom settings
- ServeMux.Use registers middleware (must be called before Handle)
- ServeMux.Handle, ServeMux.HandleFunc, and ServeMux.HandleStd register routes
- ServeMux.Mount, ServeMux.MountFunc, ServeMux.MountStd, and ServeMux.MountBare mount handlers under a prefix
- ServeMux.Reverse generates URLs for named routes
Standard library handlers and error ownership ¶
Methods ending in Std (ServeMux.HandleStd, ServeMux.MountStd) accept a standard library http.Handler instead of bhttp's error-returning Handler. Because http.Handler.ServeHTTP has no error return value, these handlers are fully responsible for writing their own error responses (status codes, headers, and body). bhttp's error-to-status-code mapping (as performed by ToStd) is not applied: whatever the handler writes is what the client receives.
Middleware registered via ServeMux.Use still runs before the handler and the response is still buffered through ResponseWriter, so middleware can inspect or [ResponseWriter.Reset] the response before the buffer is flushed. The handler's writes are otherwise passed through unchanged.
This makes the Std variants well suited for integrating third-party or stdlib handlers (e.g. http.FileServer, pprof, Prometheus metrics) that already manage their own HTTP responses.
Converting to Standard Library ¶
bhttp handlers can be converted to standard http.Handlers for use with any router or server:
handler := bhttp.HandlerFunc(myHandler) bare := bhttp.ToBare(handler) stdHandler := bhttp.ToStd(bare, bufferLimit, logger)
The conversion chain is:
Handler → BareHandler → http.Handler
ToBare extracts the context from the request, ToStd wraps with buffering and error handling.
Example ¶
package main
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"github.com/advdv/bhttp"
"github.com/cockroachdb/errors"
)
func main() {
mux := bhttp.NewServeMux()
mux.HandleFunc("GET /items/{id}", func(ctx context.Context, w bhttp.ResponseWriter, r *http.Request) error {
id := r.PathValue("id")
if id == "" {
return bhttp.NewError(bhttp.CodeBadRequest, errors.New("missing id"))
}
w.Header().Set("Content-Type", "application/json")
return json.NewEncoder(w).Encode(map[string]string{
"id": id,
"name": "Example Item",
})
}, "get-item")
// Generate URL by route name
url, _ := mux.Reverse("get-item", "123")
fmt.Println("URL:", url)
// Test the handler
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/items/42", nil)
mux.ServeHTTP(rec, req)
fmt.Println("Status:", rec.Code)
}
Output: URL: /items/123 Status: 200
Index ¶
- Variables
- func ToStd(h BareHandler, bufLimit int, logs Logger) http.Handler
- type BareHandler
- type BareHandlerFunc
- type Code
- type Error
- type Handler
- type HandlerFunc
- type Logger
- type Middleware
- type ResponseBuffer
- func (w *ResponseBuffer) FlushBuffer() error
- func (w *ResponseBuffer) FlushError() error
- func (w *ResponseBuffer) Free()
- func (w *ResponseBuffer) Header() http.Header
- func (w *ResponseBuffer) Reset()
- func (w *ResponseBuffer) Unwrap() http.ResponseWriter
- func (w *ResponseBuffer) Write(buf []byte) (int, error)
- func (w *ResponseBuffer) WriteHeader(statusCode int)
- type ResponseWriter
- type Reverser
- type ServeMux
- func (m *ServeMux) Handle(pattern string, handler Handler, name ...string)
- func (m *ServeMux) HandleFunc(pattern string, handler HandlerFunc, name ...string)
- func (m *ServeMux) HandleStd(pattern string, handler http.Handler, name ...string)
- func (m *ServeMux) Mount(pattern string, handler Handler)
- func (m *ServeMux) MountBare(pattern string, handler BareHandler)
- func (m *ServeMux) MountFunc(pattern string, handler HandlerFunc)
- func (m *ServeMux) MountStd(pattern string, handler http.Handler)
- func (m *ServeMux) Reverse(name string, vals ...string) (string, error)
- func (m *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (m *ServeMux) Use(mw ...Middleware)
- type TestLogger
Examples ¶
Constants ¶
This section is empty.
Variables ¶
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 ¶
Types ¶
type BareHandler ¶ added in v0.3.0
type BareHandler interface {
ServeBareBHTTP(w ResponseWriter, r *http.Request) error
}
BareHandler describes how middleware serves HTTP requests. In this library the signature for handling middleware BareHandler is different from the signature of "leaf" handlers: Handler.
func ToBare ¶ added in v0.3.0
func ToBare(h Handler) BareHandler
ToBare converts a handler into a bare buffered handler.
func Wrap ¶ added in v0.3.0
func Wrap(h Handler, m ...Middleware) BareHandler
Wrap 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 BareHandlerFunc ¶ added in v0.3.0
type BareHandlerFunc func(ResponseWriter, *http.Request) error
BareHandlerFunc allows casting a function to an implementation of BareHandler.
func (BareHandlerFunc) ServeBareBHTTP ¶ added in v0.3.0
func (f BareHandlerFunc) ServeBareBHTTP(w ResponseWriter, r *http.Request) error
ServeBareBHTTP implements the BareHandler interface.
type Code ¶ added in v0.3.2
type Code int
Code is an error code that mirrors the http status codes. It can be used to create errors to pass around across middleware layers to handle errors structurally.
const ( CodeUnknown Code = 0 CodeBadRequest Code = http.StatusBadRequest // RFC 9110, 15.5.1 CodePaymentRequired Code = http.StatusPaymentRequired // RFC 9110, 15.5.3 CodeForbidden Code = http.StatusForbidden // RFC 9110, 15.5.4 CodeNotFound Code = http.StatusNotFound // RFC 9110, 15.5.5 CodeMethodNotAllowed Code = http.StatusMethodNotAllowed // RFC 9110, 15.5.6 CodeNotAcceptable Code = http.StatusNotAcceptable // RFC 9110, 15.5.7 CodeProxyAuthRequired Code = http.StatusProxyAuthRequired // RFC 9110, 15.5.8 CodeRequestTimeout Code = http.StatusRequestTimeout // RFC 9110, 15.5.9 CodeConflict Code = http.StatusConflict // RFC 9110, 15.5.10 CodeGone Code = http.StatusGone // RFC 9110, 15.5.11 CodeLengthRequired Code = http.StatusLengthRequired // RFC 9110, 15.5.12 CodePreconditionFailed Code = http.StatusPreconditionFailed // RFC 9110, 15.5.13 CodeRequestEntityTooLarge Code = http.StatusRequestEntityTooLarge // RFC 9110, 15.5.14 CodeRequestURITooLong Code = http.StatusRequestURITooLong // RFC 9110, 15.5.15 CodeUnsupportedMediaType Code = http.StatusUnsupportedMediaType // RFC 9110, 15.5.16 CodeRequestedRangeNotSatisfiable Code = http.StatusRequestedRangeNotSatisfiable // RFC 9110, 15.5.17 CodeExpectationFailed Code = http.StatusExpectationFailed // RFC 9110, 15.5.18 CodeTeapot Code = http.StatusTeapot // RFC 9110, 15.5.19 (Unused) CodeMisdirectedRequest Code = http.StatusMisdirectedRequest // RFC 9110, 15.5.20 CodeUnprocessableEntity Code = http.StatusUnprocessableEntity // RFC 9110, 15.5.21 CodeLocked Code = http.StatusLocked // RFC 4918, 11.3 CodeFailedDependency Code = http.StatusFailedDependency // RFC 4918, 11.4 CodeTooEarly Code = http.StatusTooEarly // RFC 8470, 5.2. CodeUpgradeRequired Code = http.StatusUpgradeRequired // RFC 9110, 15.5.22 CodePreconditionRequired Code = http.StatusPreconditionRequired // RFC 6585, 3 CodeTooManyRequests Code = http.StatusTooManyRequests // RFC 6585, 4 CodeRequestHeaderFieldsTooLarge Code = http.StatusRequestHeaderFieldsTooLarge // RFC 6585, 5 CodeInternalServerError Code = http.StatusInternalServerError // RFC 9110, 15.6.1 CodeNotImplemented Code = http.StatusNotImplemented // RFC 9110, 15.6.2 CodeBadGateway Code = http.StatusBadGateway // RFC 9110, 15.6.3 CodeGatewayTimeout Code = http.StatusGatewayTimeout // RFC 9110, 15.6.5 CodeHTTPVersionNotSupported Code = http.StatusHTTPVersionNotSupported // RFC 9110, 15.6.6 CodeVariantAlsoNegotiates Code = http.StatusVariantAlsoNegotiates // RFC 2295, 8.1 CodeInsufficientStorage Code = http.StatusInsufficientStorage // RFC 4918, 11.5 CodeLoopDetected Code = http.StatusLoopDetected // RFC 5842, 7.2 CodeNotExtended Code = http.StatusNotExtended // RFC 2774, 7 CodeNetworkAuthenticationRequired Code = http.StatusNetworkAuthenticationRequired // RFC 6585, 6 )
func CodeOf ¶ added in v0.3.2
CodeOf returns the error's status code if it is or wraps an *Error and CodeUnknown otherwise.
Example ¶
package main
import (
"fmt"
"github.com/advdv/bhttp"
"github.com/cockroachdb/errors"
)
func main() {
// Create an error with a specific code
err := bhttp.NewError(bhttp.CodeNotFound, errors.New("user not found"))
fmt.Println("Code:", bhttp.CodeOf(err))
// Wrapped errors preserve the code
wrapped := fmt.Errorf("handler failed: %w", err)
fmt.Println("Wrapped code:", bhttp.CodeOf(wrapped))
// Non-bhttp errors return CodeUnknown
plainErr := errors.New("something went wrong")
fmt.Println("Plain error code:", bhttp.CodeOf(plainErr))
}
Output: Code: 404 Wrapped code: 404 Plain error code: 0
type Error ¶ added in v0.3.2
type Error struct {
// contains filtered or unexported fields
}
Error describes an http error.
func NewError ¶ added in v0.3.2
NewError inits a new error given the error code.
Example ¶
package main
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"github.com/advdv/bhttp"
"github.com/cockroachdb/errors"
)
func main() {
mux := bhttp.NewServeMux()
mux.HandleFunc("GET /protected", func(ctx context.Context, w bhttp.ResponseWriter, r *http.Request) error {
token := r.Header.Get("Authorization")
if token == "" {
return bhttp.NewError(bhttp.CodeUnauthorized, errors.New("missing token"))
}
if token != "Bearer secret" {
return bhttp.NewError(bhttp.CodeForbidden, errors.New("invalid token"))
}
fmt.Fprint(w, "welcome")
return nil
})
// Request without token
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/protected", nil)
mux.ServeHTTP(rec, req)
fmt.Println("No token:", rec.Code)
// Request with invalid token
rec = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodGet, "/protected", nil)
req.Header.Set("Authorization", "Bearer wrong")
mux.ServeHTTP(rec, req)
fmt.Println("Bad token:", rec.Code)
// Request with valid token
rec = httptest.NewRecorder()
req = httptest.NewRequest(http.MethodGet, "/protected", nil)
req.Header.Set("Authorization", "Bearer secret")
mux.ServeHTTP(rec, req)
fmt.Println("Valid token:", rec.Code)
}
Output: No token: 401 Bad token: 403 Valid token: 200
type HandlerFunc ¶
HandlerFunc allows casting a function to implement Handler.
func (HandlerFunc) ServeBHTTP ¶
func (f HandlerFunc) ServeBHTTP(ctx context.Context, w ResponseWriter, r *http.Request) error
ServeBHTTP implements the Handler interface.
type Logger ¶
Logger can be implemented to get informed about important states.
func NewStdLogger ¶ added in v0.3.0
type Middleware ¶
type Middleware func(BareHandler) BareHandler
Middleware for cross-cutting concerns with buffered responses.
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 (*ResponseBuffer) FlushBuffer ¶ added in v0.3.0
func (w *ResponseBuffer) FlushBuffer() error
FlushBuffer 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) 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) 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()
Free()
FlushBuffer() error
}
ResponseWriter implements the http.ResponseWriter but the underlying bytes are buffered. This allows middleware to reset the writer and formulate a completely new response.
func NewResponseWriter ¶ added in v0.3.0
func NewResponseWriter(resp http.ResponseWriter, limit int) ResponseWriter
NewResponseWriter 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.
type Reverser ¶
type Reverser struct {
// contains filtered or unexported fields
}
Reverser keeps track of named patterns and allows building URLS.
func (Reverser) NamedPattern ¶
NamedPattern will parse 's' as a path pattern while returning it as well.
type ServeMux ¶
type ServeMux struct {
// contains filtered or unexported fields
}
ServeMux is an HTTP multiplexer with buffered responses, error handling, and named routes.
func NewServeMux ¶
func NewServeMux() *ServeMux
NewServeMux creates a new ServeMux with default settings.
func NewServeMuxWith ¶ added in v0.6.0
func NewServeMuxWith(bufLimit int, logger Logger, baseMux *http.ServeMux, reverser *Reverser) *ServeMux
NewServeMuxWith creates a ServeMux with custom settings.
Example ¶
package main
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"github.com/advdv/bhttp"
)
func main() {
mux := bhttp.NewServeMuxWith(
-1, // no buffer limit
bhttp.NewTestLogger(nil),
http.NewServeMux(),
bhttp.NewReverser(),
)
mux.HandleFunc("GET /info", func(_ context.Context, w bhttp.ResponseWriter, r *http.Request) error {
reqID := r.Header.Get("X-Request-ID")
fmt.Fprintf(w, "Request ID: %s", reqID)
return nil
})
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/info", nil)
req.Header.Set("X-Request-ID", "abc-123")
mux.ServeHTTP(rec, req)
fmt.Println(rec.Body.String())
}
Output: Request ID: abc-123
func (*ServeMux) HandleFunc ¶
func (m *ServeMux) HandleFunc(pattern string, handler HandlerFunc, name ...string)
HandleFunc handles the request given the pattern using a function.
func (*ServeMux) HandleStd ¶ added in v0.7.0
HandleStd registers a standard library http.Handler for the given pattern. Middleware registered via ServeMux.Use is applied. See the package-level section "Standard library handlers and error ownership" for details on error handling behavior.
func (*ServeMux) Mount ¶ added in v0.7.0
Mount mounts a Handler on a sub-path pattern. The mounted handler receives requests with the mount prefix stripped from the path.
func (*ServeMux) MountBare ¶ added in v0.7.0
func (m *ServeMux) MountBare(pattern string, handler BareHandler)
MountBare mounts a BareHandler on a sub-path pattern. The mounted handler receives requests with the mount prefix stripped from the path. Middleware registered via Use() sees the original path; the strip happens after middleware.
func (*ServeMux) MountFunc ¶ added in v0.7.0
func (m *ServeMux) MountFunc(pattern string, handler HandlerFunc)
MountFunc mounts a HandlerFunc on a sub-path pattern. The mounted handler receives requests with the mount prefix stripped from the path.
func (*ServeMux) MountStd ¶ added in v0.7.0
MountStd mounts a standard library http.Handler on a sub-path pattern. The mounted handler receives requests with the mount prefix stripped from the path. Middleware registered via ServeMux.Use is applied and sees the original path. See the package-level section "Standard library handlers and error ownership" for details on error handling behavior.
func (*ServeMux) Reverse ¶
Reverse returns the url based on the name and parameter values.
Example ¶
package main
import (
"context"
"fmt"
"net/http"
"github.com/advdv/bhttp"
)
func main() {
mux := bhttp.NewServeMux()
mux.HandleFunc("GET /users/{id}", func(ctx context.Context, w bhttp.ResponseWriter, r *http.Request) error {
return nil
}, "get-user")
mux.HandleFunc("GET /users/{userId}/posts/{postId}", func(ctx context.Context, w bhttp.ResponseWriter, r *http.Request) error {
return nil
}, "get-user-post")
url1, _ := mux.Reverse("get-user", "42")
url2, _ := mux.Reverse("get-user-post", "42", "101")
fmt.Println(url1)
fmt.Println(url2)
}
Output: /users/42 /users/42/posts/101
func (*ServeMux) ServeHTTP ¶
func (m *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP makes the server mux implement the http.Handler interface.
func (*ServeMux) Use ¶
func (m *ServeMux) Use(mw ...Middleware)
Use allows providing of middleware.
Example ¶
package main
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"github.com/advdv/bhttp"
)
func main() {
mux := bhttp.NewServeMux()
// Add request ID middleware
mux.Use(func(next bhttp.BareHandler) bhttp.BareHandler {
return bhttp.BareHandlerFunc(func(w bhttp.ResponseWriter, r *http.Request) error {
// Set header before calling next handler
w.Header().Set("X-Request-ID", "req-123")
return next.ServeBareBHTTP(w, r)
})
})
mux.HandleFunc("GET /ping", func(ctx context.Context, w bhttp.ResponseWriter, r *http.Request) error {
fmt.Fprint(w, "pong")
return nil
})
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/ping", nil)
mux.ServeHTTP(rec, req)
fmt.Println("Body:", rec.Body.String())
fmt.Println("Request ID:", rec.Header().Get("X-Request-ID"))
}
Output: Body: pong Request ID: req-123
type TestLogger ¶ added in v0.3.0
type TestLogger struct {
NumLogUnhandledServeError int64
NumLogImplicitFlushError int64
// contains filtered or unexported fields
}
func NewTestLogger ¶ added in v0.3.0
func NewTestLogger(tb testing.TB) *TestLogger
func (*TestLogger) LogImplicitFlushError ¶ added in v0.3.0
func (l *TestLogger) LogImplicitFlushError(err error)
func (*TestLogger) LogUnhandledServeError ¶ added in v0.3.0
func (l *TestLogger) LogUnhandledServeError(err error)
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package blwa provides a batteries-included framework for building HTTP services on AWS Lambda Web Adapter (LWA).
|
Package blwa provides a batteries-included framework for building HTTP services on AWS Lambda Web Adapter (LWA). |
|
blwatest
Package blwatest provides test helpers for blwa applications.
|
Package blwatest provides test helpers for blwa applications. |
|
internal
|
|