Documentation
¶
Index ¶
- Constants
- func DecodeJSONRequestBody[T any](r *http.Request) (T, error)
- func GetLatencyFromContext(ctx context.Context) time.Duration
- func RenderBadRequest(ctx context.Context, w http.ResponseWriter, cause error)
- func RenderBadRequestWithBody(ctx context.Context, w http.ResponseWriter, bodyRenderer ResponseBodyRenderer, ...) error
- func RenderConflict(ctx context.Context, w http.ResponseWriter, cause error)
- func RenderCreated(ctx context.Context, w http.ResponseWriter)
- func RenderCreatedWithBody(ctx context.Context, w http.ResponseWriter, bodyRenderer ResponseBodyRenderer) error
- func RenderForbidden(ctx context.Context, w http.ResponseWriter, cause error)
- func RenderInternalServerError(ctx context.Context, w http.ResponseWriter, cause error)
- func RenderNoContent(ctx context.Context, w http.ResponseWriter)
- func RenderNoContentForUnauthorized(ctx context.Context, w http.ResponseWriter, cause error)
- func RenderNotFound(ctx context.Context, w http.ResponseWriter, cause error)
- func RenderOK(ctx context.Context, w http.ResponseWriter)
- func RenderOKWithBody(ctx context.Context, w http.ResponseWriter, bodyRenderer ResponseBodyRenderer) error
- func RenderRedirect(ctx context.Context, w http.ResponseWriter, r *http.Request, url string)
- func RenderUnauthorized(ctx context.Context, w http.ResponseWriter, cause error)
- func WithLatency(ctx context.Context, latency time.Duration) context.Context
- func WithRequestLog(ctx context.Context, requestLog RequestLog) context.Context
- func WithResponseLogPtr(ctx context.Context, resPtr *ResponseLog) context.Context
- type ContentType
- type HandlerInfo
- type RequestLog
- type ResponseBodyRenderer
- type ResponseLog
Constants ¶
const DefaultMaxRequestBodySize = 1 << 20 // 1MB
Variables ¶
This section is empty.
Functions ¶
func DecodeJSONRequestBody ¶
DecodeJSONRequestBody decodes request body to T using JSON decoder.
This function reads the request body up to DefaultMaxRequestBodySize. If the request body exceeds this size, the function returns http.MaxBytesError.
The request body will be closed after decoding. This function ignores any error returned by Close.
func GetLatencyFromContext ¶ added in v0.4.0
GetLatencyFromContext returns the latency stored in the context.
If the context does not contain latency, it returns 0.
func RenderBadRequest ¶
func RenderBadRequest(ctx context.Context, w http.ResponseWriter, cause error)
RenderBadRequest renders a response with status code http.StatusBadRequest without body.
The cause error will be used for ResponseLog.Error.
func RenderBadRequestWithBody ¶
func RenderBadRequestWithBody(ctx context.Context, w http.ResponseWriter, bodyRenderer ResponseBodyRenderer, cause error) error
RenderBadRequestWithBody renders a response with status code http.StatusBadRequest and body.
Both RenderHeader and RenderBody will always be called, even if RenderHeader returns an error. The errors will be joined by errors.Join.
When the bodyRenderer returns errors, this function will:
- Keep the status code as http.StatusBadRequest
- Set ResponseLog in the context (the renderer error is not stored in ResponseLog.Error)
- Return the renderer error
func RenderConflict ¶
func RenderConflict(ctx context.Context, w http.ResponseWriter, cause error)
RenderConflict renders a response with status code http.StatusConflict without body.
The cause error will be used for ResponseLog.Error.
func RenderCreated ¶
func RenderCreated(ctx context.Context, w http.ResponseWriter)
RenderCreated renders a response with status code http.StatusCreated without body.
func RenderCreatedWithBody ¶
func RenderCreatedWithBody(ctx context.Context, w http.ResponseWriter, bodyRenderer ResponseBodyRenderer) error
RenderCreatedWithBody renders a response with status code http.StatusCreated and body.
Both RenderHeader and RenderBody will always be called, even if RenderHeader returns an error. The errors will be joined by errors.Join.
When the bodyRenderer returns errors, this function will:
- Keep the status code as http.StatusCreated
- Set ResponseLog in the context (the renderer error is not stored in ResponseLog.Error)
- Return the renderer error
func RenderForbidden ¶
func RenderForbidden(ctx context.Context, w http.ResponseWriter, cause error)
RenderForbidden renders a response with status code http.StatusForbidden without body.
The cause error will be used for ResponseLog.Error.
func RenderInternalServerError ¶
func RenderInternalServerError(ctx context.Context, w http.ResponseWriter, cause error)
RenderInternalServerError renders a response with status code http.StatusInternalServerError without body.
The cause error will be used for ResponseLog.Error.
func RenderNoContent ¶
func RenderNoContent(ctx context.Context, w http.ResponseWriter)
RenderNoContent renders a response with status code http.StatusNoContent without body.
func RenderNoContentForUnauthorized ¶ added in v0.2.0
func RenderNoContentForUnauthorized(ctx context.Context, w http.ResponseWriter, cause error)
RenderNoContentForUnauthorized renders a response with status code http.StatusNoContent without body.
This function can be used to send the same success response to the client when an authentication error occurs.
The cause error will be used for ResponseLog.Error.
func RenderNotFound ¶
func RenderNotFound(ctx context.Context, w http.ResponseWriter, cause error)
RenderNotFound renders a response with status code http.StatusNotFound without body.
The cause error will be used for ResponseLog.Error.
func RenderOK ¶
func RenderOK(ctx context.Context, w http.ResponseWriter)
RenderOK renders a response with status code http.StatusOK without body.
func RenderOKWithBody ¶
func RenderOKWithBody(ctx context.Context, w http.ResponseWriter, bodyRenderer ResponseBodyRenderer) error
RenderOKWithBody renders a response with status code http.StatusOK and body.
Both RenderHeader and RenderBody will always be called, even if RenderHeader returns an error. The errors will be joined by errors.Join.
When the bodyRenderer returns errors, this function will:
- Keep the status code as http.StatusOK
- Set ResponseLog in the context (the renderer error is not stored in ResponseLog.Error)
- Return the renderer error
func RenderRedirect ¶
RenderRedirect renders a response with status code http.StatusTemporaryRedirect and a redirect url.
func RenderUnauthorized ¶
func RenderUnauthorized(ctx context.Context, w http.ResponseWriter, cause error)
RenderUnauthorized renders a response with status code http.StatusUnauthorized without body.
The cause error will be used for ResponseLog.Error.
func WithLatency ¶ added in v0.4.0
WithLatency returns a new context that carries the provided latency.
func WithRequestLog ¶
func WithRequestLog(ctx context.Context, requestLog RequestLog) context.Context
WithRequestLog returns a new context that carries a copy of the given RequestLog.
The RequestLog value is stored as a pointer internally, but this function takes the value by copy to avoid later mutations of the original affecting the stored value.
func WithResponseLogPtr ¶
func WithResponseLogPtr(ctx context.Context, resPtr *ResponseLog) context.Context
WithResponseLogPtr returns a new context that carries the provided ResponseLog pointer.
Storing a nil pointer is allowed and can be used to explicitly mark absence. The pointer is not copied; later modifications through the pointer are observable via future reads from the context.
Note: The ResponseLog should only be accessed within a single HTTP request handler chain. Concurrent access from multiple goroutines is not supported and may result in data races.
Types ¶
type ContentType ¶
type ContentType = string
ContentType represents an HTTP Content-Type header value.
These constants provide commonly used media types for convenience when setting HTTP headers (e.g. "Content-Type") or comparing values.
const ( // ContentTypeTextPlain is a content type "text/plain" ContentTypeTextPlain ContentType = "text/plain" // ContentTypeJSON is a content type "application/json" ContentTypeJSON ContentType = "application/json" // ContentTypeJSONUTF8 is a content type "application/json; charset=utf-8" ContentTypeJSONUTF8 ContentType = "application/json; charset=utf-8" // ContentTypeOctetStream is a content type "application/octet-stream" ContentTypeOctetStream ContentType = "application/octet-stream" )
type HandlerInfo ¶
type HandlerInfo struct {
// FuncName is the fully qualified name of the handler function.
FuncName string
// File is the source file path where the handler is defined.
File string
// Line is the line number in the source file where the handler is defined.
Line int
}
HandlerInfo holds metadata about the HTTP handler function that processed the request.
It includes the fully qualified function name and source location (file and line). When unavailable, use UnknownHandlerInfo.
func NewHandlerInfo ¶
func NewHandlerInfo(skip int) HandlerInfo
NewHandlerInfo returns handler information for the caller.
The skip parameter specifies the number of stack frames to skip before recording, where 0 identifies the caller of NewHandlerInfo.
func UnknownHandlerInfo ¶
func UnknownHandlerInfo() HandlerInfo
UnknownHandlerInfo returns a HandlerInfo representing an unknown handler.
func (*HandlerInfo) ToAttr ¶
func (h *HandlerInfo) ToAttr() slog.Attr
ToAttr converts the HandlerInfo to a structured slog.Attr for logging.
Returns a grouped slog.Attr with key "handler" containing:
- func_name: fully qualified function name
- file: source file path
- line: line number in the source file
Returns an empty slog.Attr if the HandlerInfo is nil.
type RequestLog ¶
type RequestLog struct {
// Timestamp is the time when the request was observed/logged.
//
// It is typically the time right before the handler starts processing the request.
Timestamp time.Time
// Method is the HTTP method of the request (e.g., "GET", "POST").
Method string
// URL is the full request URL as a string.
//
// This will be an empty string if the original request's URL was nil.
URL string
// ContentLength is the declared size of the request body in bytes.
//
// A value of -1 indicates that the length is unknown (see http.Request.ContentLength).
ContentLength int64
// Proto is the HTTP protocol version used by the client (e.g., "HTTP/1.1", "HTTP/2").
Proto string
// Host is the value of the request host (usually from the Host header).
Host string
// RemoteAddr is the client address in the form "IP:port" as reported by the server.
//
// Use GetIP to extract and parse the IP component.
RemoteAddr string
// UserAgent is the client user agent string.
UserAgent string
// RequestURI is the unmodified request-target as sent by the client.
//
// It may include the path and query string.
RequestURI string
// Referer is the URL of the resource from which the request originated.
//
// It is taken from the "Referer" header and may be empty.
Referer string
}
RequestLog represents structured HTTP request information for logging purposes.
It captures key details from an http.Request at a specific point in time.
func GetRequestLogFromContext ¶
func GetRequestLogFromContext(ctx context.Context) RequestLog
GetRequestLogFromContext returns the RequestLog stored in the context.
If the context does not contain a request log, or the stored value is nil, it returns the zero-value RequestLog.
func NewRequestLog ¶
func NewRequestLog(r *http.Request, timestamp time.Time) RequestLog
NewRequestLog creates a RequestLog from an http.Request and timestamp.
If r is nil, the returned RequestLog will be empty.
If r.URL is nil, the RequestLog.URL will be an empty string.
func (*RequestLog) GetAddr ¶ added in v0.6.0
func (l *RequestLog) GetAddr() netip.Addr
GetAddr extracts and parses the IP address from RemoteAddr.
Returns an empty netip.Addr if the RequestLog is nil, the address cannot be parsed, or the host portion is not a valid IP address.
func (*RequestLog) GetIP ¶
func (l *RequestLog) GetIP() net.IP
GetIP extracts and parses the IP address from RemoteAddr.
Returns nil if the RequestLog is nil, the address cannot be parsed, or the host portion is not a valid IP address. IPv4 addresses are returned as 4-byte representation, IPv6 as 16-byte.
func (*RequestLog) ToAttr ¶
func (l *RequestLog) ToAttr() slog.Attr
ToAttr converts the RequestLog to a structured slog.Attr for logging.
Returns a grouped slog.Attr with key "http_request" containing:
- timestamp: request timestamp in RFC3339 format
- method: HTTP method
- url: full request URL
- host: request host
- request_uri: unmodified request-target
- content_length: request body size in bytes (-1 if unknown)
- proto: HTTP protocol version
- remote_addr: client address (IP:port)
- user_agent: client user agent string
- referer: referring URL
Returns an empty slog.Attr if the RequestLog is nil.
type ResponseBodyRenderer ¶
type ResponseBodyRenderer interface {
RenderHeader(ctx context.Context, header http.Header) error
RenderBody(ctx context.Context, w io.Writer) error
}
func JSONResponse ¶
func JSONResponse(v any) (ResponseBodyRenderer, error)
func RawResponse ¶
func RawResponse(b []byte) ResponseBodyRenderer
func RawResponseWithContentType ¶
func RawResponseWithContentType(b []byte, contentType ContentType) ResponseBodyRenderer
type ResponseLog ¶
type ResponseLog struct {
// StatusCode is the HTTP status code of the response.
StatusCode int
// ResponseSize is the size of the response body in bytes.
// A value of -1 indicates that the size is unknown or not applicable.
ResponseSize int64
// Error is any error that occurred during request processing.
Error error
// HandlerInfo contains metadata about the handler that processed the request.
HandlerInfo HandlerInfo
}
ResponseLog represents structured HTTP response information for logging purposes.
It captures key details about an HTTP response at a specific point in time.
func GetResponseLogPtrFromContext ¶
func GetResponseLogPtrFromContext(ctx context.Context) *ResponseLog
GetResponseLogPtrFromContext returns the ResponseLog pointer stored in the context.
If the context does not contain a response log, or the stored value is nil, it returns nil. The returned pointer is the same instance stored in the context, so modifying the pointed value will be reflected in later reads.
Note: ResponseLog is intended for use within a single HTTP request handler chain and is not safe for concurrent access from multiple goroutines. Each HTTP request should maintain its own ResponseLog instance.
func (*ResponseLog) ToAttr ¶
func (r *ResponseLog) ToAttr(latency time.Duration) slog.Attr
ToAttr converts the ResponseLog to a structured slog.Attr for logging.
Returns a grouped slog.Attr with a key "http_response" containing:
- latency: request processing time in milliseconds
- status_code: HTTP status code
- response_size: response body size in bytes
- error: error message (included only if Error is not nil)
- handler: handler information (included only if HandlerInfo.FuncName is not empty)
Returns an empty slog.Attr if the ResponseLog is nil.