Package echo

import "funnyhaha.technology/echo"
View the source code

Overview

Package echo is an HTTP request and response service, like httpbin: it reflects requests back and produces whatever response a client asks for, so clients, proxies and the funnyhaha.technology/rfc packages can be tried out with curl.

$ curl -i https://echo.example/status/401
HTTP/1.1 401 Unauthorized
Content-Type: application/problem+json
Www-Authenticate: Bearer realm="echo"

{"title":"Unauthorized","status":401}

The routes are listed on NewAPI. The binary is in cmd/echo, and its image is built by the Dockerfile.

Subpackages

PackageDescription
funnyhaha.technology/echo/cmd/echoCommand echo serves the echo API.

Index

Constants

const (
	MaxDelay     = 10 * time.Second
	MaxTicks     = 100
	MinInterval  = 10 * time.Millisecond
	MaxInterval  = 10 * time.Second
	MaxBodyBytes = 1 << 20
)
source

Limits on what a client can ask for.

Variables

var (
	ErrInvalidCode     = errors.New("status code must be from 400 to 599")
	ErrInvalidDelay    = errors.New("delay must be whole seconds from 0 to 10")
	ErrInvalidCount    = errors.New("count must be from 1 to 100")
	ErrInvalidInterval = errors.New("interval must be a duration from 10ms to 10s")
	ErrMissingBody     = errors.New("request body is missing")
)
source

The errors the operations and wire requests declare.

Types

APIBuilder source

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

APIBuilder configures the API's handler. Its With methods return a modified copy.

NewAPI source

func NewAPI(deps APIDeps) APIBuilder

NewAPI returns a builder for the API, which serves:

Every route allows CORS requests from any origin, without credentials. It panics if a dependency is missing.

(APIBuilder) Handler source

func (b APIBuilder) Handler() http.Handler

Handler returns the API's handler.

(APIBuilder) WithLogger source

func (b APIBuilder) WithLogger(logger *slog.Logger) APIBuilder

WithLogger sets the logger for request logs.

(APIBuilder) WithTrustedProxies source

func (b APIBuilder) WithTrustedProxies(prefixes ...netip.Prefix) APIBuilder

WithTrustedProxies trusts the X-Forwarded-For entries written by proxies in these prefixes, for the client IP that /anything reports and the request log records.

APIDeps source

type APIDeps struct {
	Echo     EchoOpFunc
	EchoJSON EchoJSONOpFunc
	Status   StatusOpFunc
	Delay    DelayOpFunc
	Ticks    TicksOpFunc
}

APIDeps are the operations the API calls, one per route.

DelayOpFunc source

type DelayOpFunc func(context.Context, DelayParams) (DelayResult, error)

DelayOpFunc waits for the delay, or until its context is cancelled.

Delay source

func Delay(after func(time.Duration) <-chan time.Time) DelayOpFunc

Delay returns a DelayOpFunc that waits on after, which is time.After outside tests.

DelayParams source

type DelayParams struct {
	Delay time.Duration
}

DelayParams are the params of a DelayOpFunc.

DelayResult source

type DelayResult struct {
	Delay time.Duration
}

DelayResult is the result of a DelayOpFunc.

EchoJSONOpFunc source

type EchoJSONOpFunc func(context.Context, EchoJSONParams) (EchoJSONResult, error)

EchoJSONOpFunc reflects a JSON value.

EchoJSON source

func EchoJSON() EchoJSONOpFunc

EchoJSON returns an EchoJSONOpFunc that reflects the value unchanged.

EchoJSONParams source

type EchoJSONParams struct {
	// Value is a decoded JSON value.
	Value any
}

EchoJSONParams are the params of an EchoJSONOpFunc.

EchoJSONResult source

type EchoJSONResult struct {
	Value any
}

EchoJSONResult is the result of an EchoJSONOpFunc.

EchoOpFunc source

type EchoOpFunc func(context.Context, EchoParams) (EchoResult, error)

EchoOpFunc reflects a request.

Echo source

func Echo() EchoOpFunc

Echo returns an EchoOpFunc that reflects the request unchanged.

EchoParams source

type EchoParams struct {
	Method   string
	Path     string
	Query    url.Values
	Header   http.Header
	Body     []byte
	ClientIP netip.Addr
}

EchoParams are the params of an EchoOpFunc: the parts of a request it reflects.

EchoResult source

type EchoResult struct {
	Method   string
	Path     string
	Query    url.Values
	Header   http.Header
	Body     []byte
	ClientIP netip.Addr
}

EchoResult is the result of an EchoOpFunc: what's reflected back.

StatusOpFunc source

type StatusOpFunc func(context.Context, StatusParams) (StatusResult, error)

StatusOpFunc builds the status for a code, with the header fields RFC 9110 requires of it. It returns ErrInvalidCode for a code it can't.

Statuses source

func Statuses(bearer rfc6750.Challenge, basic rfc7617.Challenge, upgrade rfc9110.Protocol) StatusOpFunc

Statuses returns a StatusOpFunc. The statuses whose header fields RFC 9110 requires get them from its arguments:

428, 429, 431 and 511 come from RFC 6585, and every other code from rfc9110.NewStatus.

StatusParams source

type StatusParams struct {
	// Code is a 4xx or 5xx status code.
	Code int
	// RetryAfter, if positive, adds Retry-After to a 429 or 503.
	RetryAfter time.Duration
}

StatusParams are the params of a StatusOpFunc.

StatusResult source

type StatusResult struct {
	Status rfc9110.Status
}

StatusResult is the result of a StatusOpFunc. It's an HTTP status, because that's this service's subject matter.

Tick source

type Tick struct {
	N int
}

Tick is one event of a TicksOpFunc's stream, numbered from 1.

TicksOpFunc source

type TicksOpFunc func(context.Context, TicksParams) (iter.Seq2[Tick, error], error)

TicksOpFunc streams Count ticks, Interval apart. The iterator stops when its context is cancelled, yielding the context's error, and can be ranged over only once.

Ticks source

func Ticks(after func(time.Duration) <-chan time.Time) TicksOpFunc

Ticks returns a TicksOpFunc that waits on after, which is time.After outside tests, between ticks. The first tick is sent at once.

TicksParams source

type TicksParams struct {
	Count    int
	Interval time.Duration
}

TicksParams are the params of a TicksOpFunc.