httputils

package
v1.1.4 Latest Latest
Warning

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

Go to latest
Published: Jul 20, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Index

Constants

View Source
const MaxRequestBodyBytes int64 = 16 * 1024 * 1024

MaxRequestBodyBytes caps every body read through ReadBody. AWS API request payloads top out at 6 MiB (Lambda synchronous invoke) or 5 GiB streamed (S3 PutObject, which uses its own streaming path and does not call ReadBody). 16 MiB leaves headroom for unusually large API requests while preventing unbounded memory growth from attacker-controlled bodies.

Variables

This section is empty.

Functions

func DrainBody

func DrainBody(r *http.Request)

DrainBody reads and discards the request body. This is important for HTTP keep-alive, as the server needs to know the request body has been fully consumed before reusing the connection.

func EchoError

func EchoError(ctx context.Context, c *echo.Context, code int, message string, err error) error

EchoError is a helper for Echo handlers to write errors with proper logging.

func ExtractRegionFromRequest

func ExtractRegionFromRequest(r *http.Request, defaultRegion string) string

ExtractRegionFromRequest extracts the AWS region from an HTTP request. It checks the SigV4 Authorization header credential scope first, then the X-Amz-Region header, then falls back to defaultRegion.

func ExtractServiceFromRequest

func ExtractServiceFromRequest(r *http.Request) string

ExtractServiceFromRequest extracts the AWS service name from the SigV4 Authorization header credential scope (AKID/date/region/service/aws4_request). Returns an empty string if the service name cannot be determined.

func GetOperation

func GetOperation(ctx context.Context) string

GetOperation retrieves the operation name from context, or "Unknown" if not set.

func GetResource

func GetResource(ctx context.Context) string

GetResource retrieves the resource identifier from context, or "" if not set.

func ReadBody

func ReadBody(r *http.Request) ([]byte, error)

ReadBody reads the request body and returns it as a byte slice. It handles cases where r.Body might be nil (e.g. in some test environments). It re-seeds the request body so it can be read multiple times and ensures the original request body is closed. It uses a custom ReadCloser to avoid redundant reads and allocations if called multiple times. The body is capped at MaxRequestBodyBytes; reads that exceed the cap return an `*http.MaxBytesError` (use errors.As to detect and translate to a 413 response). Because this helper has no access to the originating ResponseWriter, it cannot auto-write the 413 itself — callers must handle the size-cap error and respond appropriately.

func RequestIDMiddleware

func RequestIDMiddleware() echo.MiddlewareFunc

RequestIDMiddleware returns an Echo middleware that injects an x-amz-request-id header (a new UUID) into every HTTP response.

func SanitizeHeaderString

func SanitizeHeaderString(s string) string

SanitizeHeaderString removes all characters except alphanumeric, hyphens, underscores, and periods. This breaks the taint for static analysis tools like CodeQL which flag raw header values in logs.

func SetOperation

func SetOperation(ctx context.Context, operation string) context.Context

SetOperation returns a new context with the operation name updated. This follows the idiomatic context pattern - immutable values.

func SetOperationAndResource

func SetOperationAndResource(ctx context.Context, operation, resource string) context.Context

SetOperationAndResource returns a new context with both operation and resource set. This is a convenience function to set both at once without intermediate contexts.

func SetResource

func SetResource(ctx context.Context, resource string) context.Context

SetResource returns a new context with the resource identifier updated. This follows the idiomatic context pattern - immutable values.

func WriteDynamoDBResponse

func WriteDynamoDBResponse(ctx context.Context, w http.ResponseWriter, code int, payload any)

WriteDynamoDBResponse writes a DynamoDB-style JSON response with CRC32 checksum. Sets Content-Type to "application/x-amz-json-1.0" and X-Amz-Crc32.

func WriteError

func WriteError(ctx context.Context, w http.ResponseWriter, r *http.Request, err error, code int)

WriteError writes an error response with structured logging. Uses the logger from ctx to record the error with context. Drains the request body to ensure connection reuse.

func WriteJSON

func WriteJSON(ctx context.Context, w http.ResponseWriter, code int, payload any)

WriteJSON marshals the payload to JSON, sets standard headers, and writes the response. Sets Content-Type to "application/json" and Content-Length.

func WriteS3ErrorResponse

func WriteS3ErrorResponse(ctx context.Context, w http.ResponseWriter, r *http.Request, s3Err any, code int)

WriteS3ErrorResponse writes an S3-compatible XML error response. Drains the request body and writes the error as XML.

func WriteXML

func WriteXML(ctx context.Context, w http.ResponseWriter, code int, payload any)

WriteXML writes an XML response with the given status code. The full body is buffered before writing it to the response.

Types

type OperationKey

type OperationKey struct{}

OperationKey is a type-safe context key for storing operation metadata.

type ResponseWriter

type ResponseWriter struct {
	http.ResponseWriter
	// contains filtered or unexported fields
}

ResponseWriter wraps http.ResponseWriter and tracks the HTTP status code. Use this when you need to inspect the status after WriteHeader is called.

func NewResponseWriter

func NewResponseWriter(w http.ResponseWriter) *ResponseWriter

NewResponseWriter creates a ResponseWriter that wraps the given http.ResponseWriter.

func (*ResponseWriter) StatusCode

func (w *ResponseWriter) StatusCode() int

StatusCode returns the HTTP status code that was written.

func (*ResponseWriter) Write

func (w *ResponseWriter) Write(b []byte) (int, error)

Write sets status to http.StatusOK if not already set, then delegates to wrapped ResponseWriter.

func (*ResponseWriter) WriteHeader

func (w *ResponseWriter) WriteHeader(code int)

WriteHeader writes the status code and delegates to the wrapped ResponseWriter.

type SigV4Error

type SigV4Error struct {
	Code    string
	Message string
	Status  int
}

SigV4Error is the AWS error returned when validation fails. The Code field drives the X-Amzn-Errortype header / error code clients expect.

type SigV4Validator

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

SigV4Validator cryptographically verifies AWS Signature Version 4 on incoming requests. It is OFF by default; the caller opts in via NewSigV4Validator and the EchoMiddleware. When enabled, requests whose recomputed signature does not match the Authorization header are rejected with the AWS-accurate error.

Verification re-derives the signing key from a single configured secret key (the access-key-id in the request is informational only — gopherstack is a single-tenant simulator). This mirrors how AWS validates: only the secret is secret; everything else is reconstructed from the request.

func NewSigV4Validator

func NewSigV4Validator(secretKey string) *SigV4Validator

NewSigV4Validator builds a validator that checks signatures against secretKey. A blank secretKey is treated as "test" — the common AWS dummy credential — so the default localstack-style client (AWS_SECRET_ACCESS_KEY=test) validates.

func (*SigV4Validator) EchoMiddleware

func (v *SigV4Validator) EchoMiddleware() echo.MiddlewareFunc

EchoMiddleware returns Echo middleware that validates SigV4 on every request. Requests without an Authorization header are passed through unchanged (many gopherstack internal/health/dashboard calls are unsigned); only requests that present a SigV4 Authorization header are verified. This keeps anonymous and presigned-URL flows working while still rejecting tampered signed requests.

func (*SigV4Validator) Verify

func (v *SigV4Validator) Verify(r *http.Request) *SigV4Error

Verify recomputes the SigV4 signature for r and compares it to the signature in the Authorization header. It returns nil on a match, or a *SigV4Error describing the AWS-accurate rejection otherwise. Verify reads and restores the request body so downstream handlers still see it.

Jump to

Keyboard shortcuts

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