router

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Mar 10, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package router implements a tRPC-compatible RPC server for Go.

It provides type-safe procedure registration using Go generics, middleware support, Server-Sent Events for subscriptions, batch request handling, and CORS configuration.

Basic Usage

r := router.NewRouter()
router.Query(r, "getUser", func(ctx context.Context, input GetUserInput) (User, error) {
    return db.FindUser(input.ID)
})
router.Mutation(r, "createUser", func(ctx context.Context, input CreateUserInput) (User, error) {
    return db.CreateUser(input)
})
http.ListenAndServe(":8080", r.Handler())

Middleware

Middlewares wrap procedure handlers and can reject requests, enrich context, or add logging/metrics:

r.Use(router.BearerAuth(validateToken))
r.Use(router.RateLimit(100))

Subscriptions

Subscriptions return a channel that is streamed as Server-Sent Events:

router.Subscription(r, "events", func(ctx context.Context, input struct{}) (<-chan Event, error) {
    ch := make(chan Event)
    go produceEvents(ctx, ch)
    return ch, nil
})

Nested Routers

Routers can be merged under namespace prefixes:

appRouter.Merge("user", userRouter) // user.get, user.create, etc.

Index

Constants

View Source
const (
	ErrUnauthorized = trpcerrors.ErrUnauthorized
	ErrForbidden    = trpcerrors.ErrForbidden
	ErrNotFound     = trpcerrors.ErrNotFound
	ErrBadRequest   = trpcerrors.ErrBadRequest
)

Re-export error codes for convenience.

View Source
const Version = "0.5.0"

Version is the current version of go-trpc.

Variables

View Source
var RequestIDKey = requestIDKeyType{}

RequestIDKey is the context key for the request ID set by the RequestID middleware.

Functions

func AddHeader

func AddHeader(ctx context.Context, key, value string)

AddHeader adds a response header value from within a procedure handler. Unlike SetHeader, this appends to existing values for the same key.

func GetBearerToken

func GetBearerToken(ctx context.Context) string

GetBearerToken extracts the bearer token from the Authorization header. Returns an empty string if the header is missing or not a Bearer token.

func GetClientIP

func GetClientIP(ctx context.Context) string

GetClientIP extracts the client IP address from the request. It checks X-Forwarded-For, X-Real-IP, then falls back to RemoteAddr.

func GetCookie

func GetCookie(ctx context.Context, name string) string

GetCookie returns the value of a named cookie, or an empty string if not found.

func GetHeader

func GetHeader(ctx context.Context, key string) string

GetHeader returns a single header value from the request.

func GetHeaders

func GetHeaders(ctx context.Context) http.Header

GetHeaders returns the request headers from the context.

func GetLastEventID

func GetLastEventID(ctx context.Context) string

GetLastEventID returns the Last-Event-ID header sent by reconnecting SSE clients. Returns an empty string if the header is missing (first connection).

func GetProcedureName

func GetProcedureName(ctx context.Context) string

GetProcedureName returns the current procedure name from the context.

func GetQueryParam

func GetQueryParam(ctx context.Context, name string) string

GetQueryParam returns a URL query parameter value, or an empty string if not found.

func GetRequest

func GetRequest(ctx context.Context) *http.Request

GetRequest returns the original *http.Request from the context.

func Mutation

func Mutation[I any, O any](r *Router, name string, handler func(ctx context.Context, input I) (O, error), opts ...ProcedureOption)

Mutation registers a mutation procedure on the router.

func NewError

func NewError(code int, message string) error

NewError creates a new tRPC error (convenience re-export).

func Query

func Query[I any, O any](r *Router, name string, handler func(ctx context.Context, input I) (O, error), opts ...ProcedureOption)

Query registers a query procedure on the router.

func SetCookie

func SetCookie(ctx context.Context, cookie *http.Cookie)

SetCookie sets a cookie on the response from within a procedure handler.

func SetHeader

func SetHeader(ctx context.Context, key, value string)

SetHeader sets a response header from within a procedure handler. Headers must be set before the response body is written (which happens automatically after the handler returns).

func Subscription

func Subscription[I any, O any](r *Router, name string, handler func(ctx context.Context, input I) (<-chan O, error), opts ...ProcedureOption)

Subscription registers a subscription procedure on the router. The handler returns a channel that yields events until closed. The channel is consumed via Server-Sent Events (SSE).

func WithValue

func WithValue(ctx context.Context, key, val interface{}) context.Context

WithValue is a convenience wrapper for context.WithValue.

Types

type CORSConfig

type CORSConfig struct {
	AllowedOrigins []string
	AllowedMethods []string
	AllowedHeaders []string
	MaxAge         int
}

CORSConfig holds CORS configuration.

type Handler

type Handler func(ctx context.Context, req Request) (interface{}, error)

Handler is the internal handler signature after type erasure.

type Logger

type Logger interface {
	Info(msg string, args ...any)
	Debug(msg string, args ...any)
	Error(msg string, args ...any)
}

Logger is the interface for logging within the router. Implementations must be safe for concurrent use.

var NopLogger Logger = nopLogger{}

NopLogger is a Logger that discards all messages. Use it with WithLogger to disable logging.

func LoggerFunc

func LoggerFunc(f func(format string, args ...any)) Logger

LoggerFunc adapts a single printf-style function into a Logger. All levels (Info, Debug, Error) call the same function.

type Middleware

type Middleware func(next Handler) Handler

Middleware wraps a Handler, allowing pre/post processing.

func APIKeyAuth

func APIKeyAuth(header string, validate func(ctx context.Context, key string) (context.Context, error)) Middleware

APIKeyAuth returns a middleware that validates an API key from a custom header. The validate function receives the key value and should return an enriched context or an error.

func BearerAuth

func BearerAuth(validate func(ctx context.Context, token string) (context.Context, error)) Middleware

BearerAuth returns a middleware that validates Bearer tokens from the Authorization header. The validate function receives the token and should return an enriched context (e.g. with user info) or an error.

func LoggingMiddleware

func LoggingMiddleware(logger Logger) Middleware

LoggingMiddleware returns a middleware that logs each procedure call with its name, duration, and error status.

func MaxConnectionsPerIP

func MaxConnectionsPerIP(limit int) Middleware

MaxConnectionsPerIP returns a middleware that limits the number of concurrent requests from a single IP address. Useful for preventing a single client from exhausting server resources, especially with long-lived SSE subscriptions.

func MaxInputSize

func MaxInputSize(bytes int) Middleware

MaxInputSize returns a middleware that rejects requests whose input payload exceeds the given byte limit. Useful for preventing oversized messages.

func RateLimit

func RateLimit(requestsPerSecond int) Middleware

RateLimit returns a middleware that limits the number of requests per second across all procedures. Excess requests receive a TOO_MANY_REQUESTS error.

func RateLimitByKey

func RateLimitByKey(requestsPerSecond int, keyFunc func(ctx context.Context) string) Middleware

RateLimitByKey returns a middleware that limits requests per second per key. The keyFunc extracts the rate-limiting key from the context (e.g. client IP, user ID). Inactive limiters are cleaned up periodically to prevent memory growth.

func RequestID

func RequestID() Middleware

RequestID returns a middleware that generates a unique request ID for each call. The ID is stored in context (retrieve via ctx.Value(router.RequestIDKey)) and set as the X-Request-ID response header.

func Timeout

func Timeout(d time.Duration) Middleware

Timeout returns a middleware that cancels procedure execution after the given duration.

type Option

type Option func(*Router)

Option configures a Router.

func WithBasePath

func WithBasePath(path string) Option

WithBasePath sets the URL prefix for the router (default: "/trpc"). The router will strip this prefix from incoming request paths.

func WithLogger

func WithLogger(l Logger) Option

WithLogger sets the logger for the router. Pass NopLogger to disable logging entirely.

func WithTransformer

func WithTransformer(t Transformer) Option

WithTransformer sets the data transformer for the router. The transformer handles serialization formats like superjson. Implementations must be safe for concurrent use.

type ProcedureOption

type ProcedureOption func(*procedure)

ProcedureOption configures a procedure at registration time.

func WithMiddleware

func WithMiddleware(mws ...Middleware) ProcedureOption

WithMiddleware attaches middlewares to a specific procedure. These run after global middlewares set via Router.Use().

type ProcedureType

type ProcedureType string

ProcedureType is the type of a tRPC procedure.

const (
	ProcedureQuery        ProcedureType = "query"
	ProcedureMutation     ProcedureType = "mutation"
	ProcedureSubscription ProcedureType = "subscription"
)

type Request

type Request struct {
	Input []byte
}

Request holds the raw JSON input for a procedure call.

type Router

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

Router is the main tRPC router that holds procedures and middlewares.

func NewRouter

func NewRouter(opts ...Option) *Router

NewRouter creates a new Router with optional configuration.

func (*Router) Handler

func (r *Router) Handler() http.Handler

Handler returns an http.Handler that serves the tRPC protocol.

func (*Router) Merge

func (r *Router) Merge(prefix string, other *Router)

Merge merges another router's procedures under a namespace prefix.

func (*Router) PrintRoutes

func (r *Router) PrintRoutes(basePath string)

PrintRoutes logs all registered procedures via the router's logger.

func (*Router) Procedures

func (r *Router) Procedures() map[string]*procedure

Procedures returns the registered procedures (used by codegen/schema).

func (*Router) ServeHTTP

func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)

ServeHTTP implements http.Handler.

func (*Router) Use

func (r *Router) Use(m Middleware)

Use adds a middleware to the router.

func (*Router) WithCORS

func (r *Router) WithCORS(cfg CORSConfig)

WithCORS configures CORS for the router.

type SubscriptionHandler

type SubscriptionHandler func(ctx context.Context, req Request) (<-chan interface{}, error)

SubscriptionHandler returns a channel that yields events until closed.

type SuperJSONTransformer

type SuperJSONTransformer struct{}

SuperJSONTransformer handles the superjson wire format used by @trpc/client when configured with transformer: superjson. It auto-detects whether input is in superjson format or plain JSON.

func (SuperJSONTransformer) TransformInput

func (t SuperJSONTransformer) TransformInput(raw []byte) ([]byte, bool, error)

TransformInput detects the superjson envelope {"json": ..., "meta": ...} and extracts the "json" field. Plain JSON passes through unchanged.

func (SuperJSONTransformer) TransformOutput

func (t SuperJSONTransformer) TransformOutput(data interface{}) (interface{}, error)

TransformOutput wraps the output data in a superjson envelope.

type TrackedEvent

type TrackedEvent struct {
	ID   string
	Data interface{}
}

TrackedEvent wraps a subscription value with a custom event ID for tracked() semantics. When a subscription handler sends a TrackedEvent on its channel, the SSE stream uses the provided ID instead of an auto-incrementing counter. This enables clients to resume from where they left off via the Last-Event-ID header on reconnect.

Usage in a handler:

ch <- router.TrackedEvent{ID: "msg-42", Data: myPayload}

type Transformer

type Transformer interface {
	// TransformInput checks if the raw input uses the transformer envelope format
	// (e.g. {"json": ..., "meta": ...}) and extracts the plain JSON.
	// Returns the plain JSON bytes, whether transformation was applied, and any error.
	TransformInput(raw []byte) ([]byte, bool, error)

	// TransformOutput wraps the output data in the transformer envelope format.
	TransformOutput(data interface{}) (interface{}, error)
}

Transformer handles serialization/deserialization of tRPC wire formats like superjson. Implementations must be safe for concurrent use.

type Validator

type Validator interface {
	Validate() error
}

Validator is an optional interface that input structs can implement to perform validation after JSON unmarshaling but before the handler. Return a *TRPCError to control the error code, or any error for BAD_REQUEST.

Jump to

Keyboard shortcuts

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