wrouter

package
v2.87.0 Latest Latest
Warning

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

Go to latest
Published: Oct 23, 2024 License: Apache-2.0 Imports: 9 Imported by: 10

README

wrouter

wrouter provides an abstraction for an opinionated HTTP router that defines contracts that make it effective for usage with witchcraft-logging-go loggers. It also defines an adapter interface that must be implemented and supplied to actually perform the routing.

Purpose

wrouter.Router exists as a common interface for registering routes with path parameters of a certain form and exposing a common way to access the path parameters and provide consistent pre and post-request hooks with relevant information.

This allows application/server-level code to perform route registration against the single defined interface in wrouter while still providing flexibility to switch out the actual implementation of the router itself.

Overview

The wrouter.Router interface defines a router on which routes can be registered. Routes are registered using the following function:

Register(method string, path PathTemplate, handler http.Handler, perms RequestParamPerms) error

This function registers the provided handler to deal with requests with the provided method that match the specified path template and uses the specified permissions to determine whether or not request parameters are safe, unsafe or forbidden.

PathTemplate is the template that defines the paths that should be handled by the provided handler. Details on the acceptable format for path templates are detailed in the "PathTemplate" section.

The wrouter.Router can be configured with a RouteHandler provider. When this is done, whenever a registered endpoint is handled, a RouteHandler is created and information about the endpoint being invoked is provided to the handler before and after the request is executed.

The wrouter.Router interface defines a contract for how endpoints are registered and provides hooks for handling the request, but it does not actually perform any routing itself. The wrouter.RouterImpl interface defines the interface that must be satisfied to implement the actual routing, and an instance of this interface must be provided to create a wrouter.Router.

PathTemplate

PathTemplate specifies a pattern that is used to match endpoints. A PathTemplate can be specified as a string that matches the following rules:

  • Must start with a '/'
  • Composed of one or more parts that are separated by a slash ('/')
  • A "part" may be one of 3 things:
    • Literal: one or more "plain characters" (defined as alphanumeric characters, '-', '_' and '.')
    • Path param: one or more "plain characters" within a single open and close curly brace
    • Trailing path param: if the part is the final part, it may be one or more "plain characters" followed by a single '*' within a single open and close curly brace

For path params and trailing path params, the "plain characters" within the curly braces define the name of the path parameter. All path parameter names in a given template must be unique (ignoring case).

Parts match request paths in the following manner:

  • Literal segments match segments IFF all characters in the segment match
  • Path param segments match any non-separator value in its segment
  • Trailing path param segments match all characters in the final segment (including any separators)

For example, consider the following template:

/product/{productId}/filePath/{filePath*}

This template would match the request path /product/foo123/filePath/var/dir/file.txt, with path param values productId="foo123" and filePath="var/dir/file.txt".

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func PathParams

func PathParams(r *http.Request) map[string]string

Types

type ParamPerms

type ParamPerms interface {
	// Safe returns true if the parameter with the provided name is safe to log. Case-insensitive.
	Safe(paramName string) bool
	// Forbidden returns true if the provided parameter is forbidden from being logged (that is, it should not be logged
	// at all, even as an unsafe parameter). Case-insensitive.
	Forbidden(paramName string) bool
}

func NewCombinedParamPerms

func NewCombinedParamPerms(paramPerms ...ParamPerms) ParamPerms

type PathSegment

type PathSegment struct {
	Type  SegmentType
	Value string
}

type PathTemplate

type PathTemplate interface {
	Template() string
	Segments() []PathSegment
}

func NewPathTemplate

func NewPathTemplate(in string) (PathTemplate, error)

NewPathTemplate creates a new PathTemplate using the provided path. The provided path must be of the following form:

  • Must start with '/'
  • Must contain only alphanumeric characters and '_', '{', '}', '/', '.', '-', and '*'
  • Path parameters must be of the form "{paramName}", where paramName must be an alphanumeric string
  • Path parameters that occur at the end of a path can take the form "{paramName*}", in which case the "*" signifies that the parameter is a trailing path parameter
  • For trailing path parameters, the value of the parameter will be the string that occurs after the final '/' that precedes the variable
  • For example, a route registered with path "/pkg/{pkgPath*}" matched against the request "/pkg/product/1.0.0/package.tgz" will result in a path parameter value of "product/1.0.0/package.tgz"

type RequestHandlerMiddleware

type RequestHandlerMiddleware func(rw http.ResponseWriter, r *http.Request, next http.Handler)

RequestHandlerMiddleware is registered on a router and runs on all requests before the path template and params are parsed. Implementations must call the 'next' handler or write a response to the ResponseWriter.

type RequestVals

type RequestVals struct {
	Spec          RouteSpec
	PathParamVals map[string]string
	ParamPerms    RouteParamPerms
	MetricTags    metrics.Tags
	// DisableTelemetry instructs the logging middleware to skip over
	// generating metrics, request, and trace logs for a request.
	DisableTelemetry bool
}

type ResponseVals

type ResponseVals struct {
	RespStatus  int
	RespSize    int64
	ReqDuration time.Duration
}

type RootRouter

type RootRouter interface {
	http.Handler
	Router

	AddRequestHandlerMiddleware(handlers ...RequestHandlerMiddleware)
	AddRouteHandlerMiddleware(handlers ...RouteHandlerMiddleware)

	// RegisterNotFoundHandler registers a handler to produce 404 responses.
	// It should be called after all middlewares are added to the router.
	RegisterNotFoundHandler(handler http.Handler)
}

func New

func New(impl RouterImpl, params ...RootRouterParam) RootRouter

type RootRouterParam

type RootRouterParam interface {
	// contains filtered or unexported methods
}

func RootRouterParamAddRequestHandlerMiddleware

func RootRouterParamAddRequestHandlerMiddleware(reqHandler ...RequestHandlerMiddleware) RootRouterParam

func RootRouterParamAddRouteHandlerMiddleware

func RootRouterParamAddRouteHandlerMiddleware(routeReqHandler ...RouteHandlerMiddleware) RootRouterParam

type RouteHandlerMiddleware

type RouteHandlerMiddleware func(rw http.ResponseWriter, r *http.Request, reqVals RequestVals, next RouteRequestHandler)

RouteHandlerMiddleware runs on requests after the path template and params are parsed. If registered on a router, it runs on all routes. If registered on a specific route using RouteMiddleware, will run on the specific registered route after router-global middlewares. Implementations must call the 'next' handler or write a response to the ResponseWriter.

type RouteParam

type RouteParam interface {
	// contains filtered or unexported methods
}

func DisableTelemetry added in v2.8.0

func DisableTelemetry() RouteParam

func ForbiddenHeaderParams

func ForbiddenHeaderParams(forbiddenParams ...string) RouteParam

func ForbiddenPathParams

func ForbiddenPathParams(forbiddenParams ...string) RouteParam

func ForbiddenQueryParams

func ForbiddenQueryParams(forbiddenParams ...string) RouteParam

func MetricTags

func MetricTags(tags metrics.Tags) RouteParam

func RouteMiddleware added in v2.30.0

func RouteMiddleware(middleware RouteHandlerMiddleware) RouteParam

RouteMiddleware configures the provided middleware to run on requests matching this specific route.

func RouteParamPermsParam

func RouteParamPermsParam(perms RouteParamPerms) RouteParam

func SafeHeaderParams

func SafeHeaderParams(safeParams ...string) RouteParam

func SafePathParams

func SafePathParams(safeParams ...string) RouteParam

func SafeQueryParams

func SafeQueryParams(safeParams ...string) RouteParam

type RouteParamPerms

type RouteParamPerms interface {
	PathParamPerms() ParamPerms
	QueryParamPerms() ParamPerms
	HeaderParamPerms() ParamPerms
}

type RouteRequestHandler

type RouteRequestHandler func(rw http.ResponseWriter, r *http.Request, reqVals RequestVals)

type RouteSpec

type RouteSpec struct {
	Method       string
	PathTemplate string
}

RouteSpec is the specification of a full route. Consists of the HTTP method and path template for the route.

type Router

type Router interface {
	// Register registers the provided handler for this router for the provided method (GET, POST, etc.) and path.
	// The RouteParam parameters specifies any path, query or header parameters that should be considered safe or
	// forbidden for the purposes of logging.
	Register(method, path string, handler http.Handler, params ...RouteParam) error

	// RegisteredRoutes returns a slice of all of the routes registered with this router in sorted order.
	RegisteredRoutes() []RouteSpec

	// Get is a shorthand for Register(http.MethodGet, path, handler, params...)
	Get(path string, handler http.Handler, params ...RouteParam) error

	// Head is a shorthand for Register(http.MethodHead, path, handler, params...)
	Head(path string, handler http.Handler, params ...RouteParam) error

	// Post is a shorthand for Register(http.MethodPost, path, handler, params...)
	Post(path string, handler http.Handler, params ...RouteParam) error

	// Put is a shorthand for Register(http.MethodPut, path, handler, params...)
	Put(path string, handler http.Handler, params ...RouteParam) error

	// Patch is a shorthand for Register(http.MethodPatch, path, handler, params...)
	Patch(path string, handler http.Handler, params ...RouteParam) error

	// Delete is a shorthand for Register(http.MethodDelete, path, handler, params...)
	Delete(path string, handler http.Handler, params ...RouteParam) error

	// Subrouter returns a new Router that is a child of this Router. A child router is effectively an alias to the root
	// router -- any routes registered on the child router are registered on the root router with all of the prefixes up
	// to the child router.
	Subrouter(path string, params ...RouteParam) Router

	// Path returns the path stored by this router. The path is empty for the root router, while subrouters will return
	// only the portion of the path managed by the subrouter.
	Path() string

	// Parent returns the parent router of this Router, or nil if this router is the root router.
	Parent() Router

	// RootRouter returns the RootRouter for this router (which may be itself).
	RootRouter() RootRouter
}

type RouterImpl

type RouterImpl interface {
	// RouterImpl must implement http.Handler
	http.Handler

	// Register registers the provided handler for this router for the provided method (GET, POST, etc.) and
	// pathSegments.
	Register(method string, pathSegments []PathSegment, handler http.Handler)

	// PathParams returns the path parameters for the provided request. The size of the returned slice must match
	// the number of parameters in the path. The variable names of the parameters in the path are provided in order
	// in the "pathVarNames" slice.
	PathParams(req *http.Request, pathVarNames []string) map[string]string

	// RegisterNotFoundHandler registers a handler that is used to handle any requests that do not match any registered routes on the router.
	// If not provided, the implementation's default behavior is used (typically returns an http.Error with a 404 response code).
	RegisterNotFoundHandler(handler http.Handler)
}

type SegmentType

type SegmentType int
const (
	LiteralSegment SegmentType = iota
	PathParamSegment
	TrailingPathParamSegment
)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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