Back to

Package capstan

Latest Go to latest

The latest major version is .

Published: Sep 13, 2020 | License: NCSA | Module:



var DefaultMappableNodeFunc = func() mappableNode {
	return &binaryTree{}

DefaultMappableNodeFunc is the default mappableNode generator used whenever a mappableNodeFunc has not been assigned to the radix trie.

var NewScanner = utils.NewScanner

NewScanner pseudo-alias for utils.NewScanner. Used by CLI to abstract away OS differences when scanning end-of-line ("\n" vs "\r\n").

var NoColor string

NoColor flag. If set to anything but the empty string, this will enable NO_COLOR processing.

func AddPreLaunchFunc

func AddPreLaunchFunc(fn PreLaunchFunc)

func ArrayMapperFunc

func ArrayMapperFunc() mappableNode

ArrayMapperFunc returns a new, initialized arrayNode.

func BinaryTreeMapperFunc

func BinaryTreeMapperFunc() mappableNode

BinaryTreeMapperFunc returns a new binary tree.

func DependencyMapper

func DependencyMapper() *mappers.DependencyMapper

DependencyMapper is a convenience function for creating new dependency mappers.

func InitNetwork

func InitNetwork() (err error, errc chan error, close chan struct{})

func Listen

func Listen(network, addr string) (net.Listener, error)

func New

func New(conf ...*config.Config) *application

func NewMappedLoader

func NewMappedLoader(def http.Handler) *mappedLoader

NewMappedLoader returns a map-backed loader for multi-application support. Map-backed loaders can only map hostnames to handlers and cannot map base paths.

The application loader interface is defined as an internal API interface (see internal/api/application.go for ApplicationLoader).

func NewMappedNode

func NewMappedNode() *mappedNode

NewMappedNode returns a new, initialized mappedNode.

func NewMultiAppProxy

func NewMultiAppProxy(loader api.ApplicationLoader) *multiAppProxy

func NewProxyTrie

func NewProxyTrie() *proxyTrie

NewProxyTrie returns a root radix trie node.

func NewRadixLoader

func NewRadixLoader(def http.Handler) *radixLoader

NewRadixLoader returns a loader backed by a radix trie providing longest matching prefix support. If you need to match both the hostname and the base path for routing incoming requests per-application, use this loader.

Be aware that there are some limitations with assigning handlers via longest matching prefixes. In particular, the radix loader is NOT path aware, meaning that a request containing the hostname + base path assignment of "" will, by its nature, also match "" and any derivative thereafter.

The intent behind this loader is to match the first hostname + base path segment of the incoming request, pass it along to the assigned application, and allow that application to determine whether the request should be handled or an error should be returned.

func NewTrieNode

func NewTrieNode(label rune, prefix string, fn mappableNodeFunc) *proxyTrie

NewTrieNode returns a new radix trie node for use within a radix trie root node.

func Relaunch

func Relaunch() error

Relaunch the current binary inheriting all socket connection file descriptors.

This should be called from a goroutine. Parent/child process management is not handled by this function.

func RenderErrorFunc

func RenderErrorFunc(path, filepattern string) func(*Router) func(Context)

RenderErrorFunc is an error function that uses the Context-specified renderer. If the Context has no renderer enabled, or otherwise encounters and error, this will return an error result from the default error handling function.

This function encapsulated multiple layers of functions to reduce the responsibility of the caller.

func Restart

func Restart() error

Restart the current binary without inheriting socket file descriptors. For blank slate reinitialization, this is the best method to call. The parent process environment, current working directory, command line arguments, and STDIN, STDOUT, and STDERR are inherited by the child process.

Consider using Router.Rebind() instead of Restart unless you need to listen on different ports.

Be aware that there appears to be a bug with fsnotify in that O_CLOEXEC on its file descriptors isn't honored. You should consider closing any fsnotify watchers that are active before this call if you don't want to leak descriptors.

This should be called from a goroutine. Parent/child process management is not handled by this function.

func StopListening

func StopListening(listener net.Listener) error

func URLForGen

func URLForGen(router *Router, external bool) func(string, ...string) string

URLForGen returns a URLFor generator for each configured renderer. This will be attached to the global renderer first, if configured, and then to each route-specific view renderer if supplied.

type Application

type Application interface {
	BindGroup(path string) *RouterGroup
	Bind(controller Controller) error
	ReplaceController(from, to Controller) error
	ReplacePath(from, to string)
	Unmount(path string)
	UnmountController(controller Controller) error
	UnmountGroup(path string) error
	SetMiddleware(middleware ...func(http.Handler) http.Handler) Application
	SetDefaultRenderer(renderer render.Renderer) Application
	RegisterShutdownHook(hook ShutdownHook)
	Listen() error
	Config() *config.Config
	Dependencies() *mappers.DependencyMapper
	Logger() *logging.Log
	Router() *Router
	Extensions() *ExtensionManager
	Reload(config *config.Config)

type ApplicationConfig

type ApplicationConfig = config.ApplicationConfig

ApplicationConfig is the top-level pseudo-alias for Capstan's application configuration. Warning: This entity may be deprecated in a future version since CLI application support has been dropped (that's up to the caller).

type BaseController

type BaseController struct {

	// Middleware defined for this controller.
	Middleware Middleware

	// Name to assign to this controller. Leave empty to automatically deduce
	// the name from the implementing struct.
	Name string

	// Path against which this controller will bind its routes. This may have
	// special meaning for index and other methods (e.g. custom).
	Path string

	// Paths to additionally assign to this controller and its methods. Not
	// currently used.
	Paths map[string][]string

	// Prefix to prepend to the controller's symbolic name. This may be useful
	// for namespacing controller references for reversing the URL in templates.
	Prefix string

	// OptionalSlash indicates the trailing slash is optional. It is usually
	// advised to set this via the Path component.
	OptionalSlash bool

	// Endpoints is a list of custom endpoints attached to this controller.
	Endpoints map[string]RouteFlag

	// MandatoryNoSlash indicates the trailing slash must not be present. It is
	// usually advised to set this via the Path component.
	MandatoryNoSlash bool

	// MandatorySlash indicates the trailing slash is required. It is usually
	// advised to set this via the Path component.
	MandatorySlash bool

	// SlashIsDefault indicates the presence or absence of the trailing slash is
	// the default state. This flag only holds meaning when OptionalSlash is set
	// to true. It is usually advised to set this via the Path component by
	// including a slash followed by a question mark ("/?") to indicate that the
	// slash is optional and the default redirection target.
	SlashIsDefault bool

	// NoInterpolation disables path interpolation and mandates the flags
	// (above) to configure the route slash states. This is useful for routes
	// where the special characters used to communicate slash behavior are
	// required as part of the route and should be accepted as literals.
	NoInterpolation bool

	// WebSocketPath, if set, will attach the WebSocket() method to the
	// specified path underneath the path defined for this controller.
	// Recommended.
	// Leave this blank if your controller is intended strictly for websocket
	// handling.
	WebSocketPath string

	// Upgrader is the configured websocket upgrader via gorilla/websocket. This
	// provides both the configuration details for websocket connections in
	// addition to bound methods for upgrading the connection. If this is nil
	// and the controller implements the WebSocketHandler interface, the default
	// upgrader will be used instead.
	Upgrader *websocket.Upgrader

	// Renderer reference for this controller. This may be unique to each
	// controller or may be set globally via a helper.
	Renderer render.Renderer

	// BeforeResponse bindings specifically used for this controller.
	BeforeResponse []func(Context, *Route) error

	// AfterResponse bindings specifically used for this controller.
	AfterResponse []func(Context, error) error

	// Index path override. This may contain a path component, a single slash
	// indicating the path terminates with this index, a slash followed by a
	// question mark which indicates the slash is optional, or a slash followed
	// by an exclamation point indicating the route must not terminate with a
	// slash.
	Index string

	// Get overrides the default path for GET requests, appending the path
	// component specified here.
	Get string

	// Post overrides the default path for POST requests, appending the path
	// component specified here.
	Post string

	// Put overrides the default path for PUT requests, appending the path
	// component specified here.
	Put string

	// Patch overrides the default path for PATCH requests, appending the path
	// component specified here.
	Patch string

	// Delete overrides the default path for DELETE requests, appending the path
	// component specified here.
	Delete string

	// Head overrides the default path for HEAD requests, appending the path
	// component specified here.
	Head string
	// contains filtered or unexported fields

type Binder

type Binder interface {

Binder controllers are those that wish to implement or handle binding themselves. Consequently, a *Router is passed as the Bind() function's sole argument such that the controller may use it to interface directly with the router instance or may call Router.Mux() to use the muxer directly. If an implementation uses the latter, the underlying configured go-chi instance is exposed for external management.

type Config

type Config = config.Config

Config is the top-level pseudo-alias for Capstan's configuration struct. Provided for import convenience.

type ConnectHandler

type ConnectHandler interface {
	Connect(Context) error

type ContentType

type ContentType string

ContentType determines the content type for a request. This is used primarily by the Capstan Context entity to determine how the response should be generated.

const (
	TextPlain       ContentType = "text/plain"
	TextHTML        ContentType = "text/html"
	ApplicationJSON ContentType = "application/json; charset=utf8"

type Context

type Context interface {
	Float(string) (float64, error)
	FloatDefault(string, float64) float64
	Int(string) (int64, error)
	IntDefault(string, int64) int64
	Param(string) string
	ParamDefault(string, string) string
	Params(string) []string
	String(string) (string, error)
	StringDefault(string, string) string
	In(interface{}) error
	JSON(interface{}) error
	ParamTypes() map[string]string
	Render(string, interface{}) error
	Renderer() (render.ContextRenderer, error)
	Headers() http.Header
	Request() *http.Request
	Response() http.ResponseWriter
	RequestContext(key string, value interface{})
	Route() *Route
	WebSocket() *websocket.Conn
	Session() session.Session
	URLFor(string) *URLBuilder
	Write([]byte) (int, error)
	WriteJSON(interface{}) error
	HasError() error
	Error() string
	Code() int

func MakeMiddlewareContext

func MakeMiddlewareContext(w http.ResponseWriter, r *http.Request) Context

MakeMiddlewareContext returns a Context instance that's suitable for use within middleware. In this case, Type is the empty string, and ParamTypes is an empty map.

func MakeRouteContext

func MakeRouteContext(w http.ResponseWriter, r *http.Request, rt *Route) Context

type ContextMaker

type ContextMaker func(http.ResponseWriter, *http.Request, *Route) Context

type Controller

type Controller interface {
	// contains filtered or unexported methods

type DeleteHandler

type DeleteHandler interface {
	Delete(Context) error

type DependencyMapperExtension

type DependencyMapperExtension interface {

	// Dependency name and value for automatically binding this extension into
	// the dependency mapper. Most extensions will prefer doing this manually
	// via calling the dependency mapper directly after SetServer passes in the
	// active Capstan.Server instance, but implementing this interface allows
	// the Capstan extension manager to perform the function automatically. The
	// returned interface may be the extension itself or it may be any other
	// value/structure used by the extension.
	// Bear in mind that whatever value is exported via this method must also be
	// importable from the defined controllers that rely on the dependency.
	Dependency() (string, interface{})

type Endpoint

type Endpoint func(Context) error

Endpoint defines functions that serve as Capstan endpoints. These are usually members of a struct and there's currently no provision for creating "bare" endpoints.

type EnvironmentConfig

type EnvironmentConfig = config.EnvironmentConfig

EnvironmentConfig is the top-level pseudo-alias for Capstan's environment configuration.

The environment configurations allows one to configure a Capstan container when running in multiapp mode, allowing individualized versions, names, or descriptions per application while presenting different information for the containing environment.

type Extension

type Extension interface {
	// Name for this extension; symbolic.
	Name() string

	// Provides indicates the dependency fulfilled by this extension.
	Provides() string

	// Requires indicates which dependency or dependencies must be loaded prior
	// to this extension.
	Requires() []string

	// Init this extension. This is called after the extension has been loaded;
	// for extensions that have dependencies on other extensions, this is called
	// after the dependency has been loaded. Circular dependencies will result
	// in a panic.
	Init(app Application)

type ExtensionManager

type ExtensionManager struct {
	// contains filtered or unexported fields

func NewExtensionManager

func NewExtensionManager(app Application) *ExtensionManager

func (*ExtensionManager) Init

func (m *ExtensionManager) Init() *ExtensionManager

func (*ExtensionManager) Register

func (m *ExtensionManager) Register(extension Extension) error

type GetHandler

type GetHandler interface {
	Get(Context) error

type HTTPServer

type HTTPServer struct {
	// contains filtered or unexported fields

func (*HTTPServer) Listener

func (h *HTTPServer) Listener() net.Listener

func (*HTTPServer) Serve

func (h *HTTPServer) Serve(listener net.Listener) error

type HeadHandler

type HeadHandler interface {
	Head(Context) error

type IndexHandler

type IndexHandler interface {
	Index(Context) error

type Listener

type Listener interface {

type ListenerTLSConfig

type ListenerTLSConfig struct {
	// CertPath is the location of a TLS certificate on the file system.
	CertPath string
	// KeyPath is the location of the server's private key on the file system.
	KeyPath string
	// CertBytes is a PEM-encoded certificate.
	CertBytes []byte
	// KeyBytes is a PEM-encoded private key.
	KeyBytes []byte

type MapValues

type MapValues = render.MapValues

MapValues is a top-level pseudo-alias for Capstan's wrapper type render.MapValues wrapping the pongo2 Context.

type MapperHandler

type MapperHandler interface {
	Mapper() map[string]RouteMap

MapperHandler returns a map of a route (map key) and the endpoint + method (RouteMap) it should be bound to. MapperHandlers are controllers that define their own route-to-endpoint handling routines.

type Middleware

type Middleware chi.Middlewares

Middleware is a pseudo-alias for go-chi's awkwardly-named "Middlewares."

type MiddlewareExtension

type MiddlewareExtension interface {

	// Middleware should return any middleware required by this extension.
	Middleware() []func(http.Handler) http.Handler

type MiddlewareFunc

type MiddlewareFunc func(http.Handler) http.Handler

MiddlewareFunc defines the type used by middleware declarations. This is provided mostly for convenience as middleware will generally define the returned handler function directly rather than assigning it to a type.

type MiddlewareHandler

type MiddlewareHandler interface {
	Middleware() []func(http.Handler) http.Handler

MiddlewareHandler, when implemented, allows controllers to return middleware that utilizes attached fields and methods as internal context. This is useful if your middleware requires access to a database or other dependencies (including injected dependencies).

type MultiAppConfig

type MultiAppConfig = config.MultiAppConfig

MultiAppConfig is the top-level pseudo-alias for Capstan's multi-application support. This controls multiapp behavior when muli-application mode has been enabled by calling Application.AttachApplication.

type MultiAppProxyHandler

type MultiAppProxyHandler interface {
	Loader() api.ApplicationLoader

MultiAppProxyHandler defines the interface to expose for types supporting multi-application loading.

type OptionsHandler

type OptionsHandler interface {
	Options(Context) error

type PatchHandler

type PatchHandler interface {
	Patch(Context) error

type PostHandler

type PostHandler interface {
	Post(Context) error

type PreLaunchFunc

type PreLaunchFunc func() error

type ProxyHandler

type ProxyHandler interface {
	// ServeHTTP allows ProxyHandler to implement http.Handler.
	ServeHTTP(http.ResponseWriter, *http.Request)

	// Switch the current router to a new router instance.

ProxyHandler is the interface that must be implemented by types that intend to be used as proxy handlers. Proxy handlers may be comparatively simple, such as the `proxy` type, or they may be more complex and implement host-lookup functionality such as the `multiAppProxy` type.

Proxies are required in order to support rebinding and endpoint deletion since go-chi doesn't currently allow us to overwrite or delete endpoints directly. So, what we do instead, is to regenerate the go-chi bindings when a rebind or endpoint deletion is requested, call Switch() on the proxy, and "switch" to the new chi.Router.

Multiple proxies are arranged in a hierarchical structure, such as for multiapp support. In this case, the multiapp proxy handles dispatching requests based on the incoming domain, path, or domain + path, and then passes it to the underlying `proxy` which performs the rest of the work. This allows us to Switch() on a per-application bases, as required, while still supporting multiple applications within the same Capstan-hosted instance.

type PutHandler

type PutHandler interface {
	Put(Context) error

type Route

type Route struct {

	// Name of this handler. This is a symbolic name
	Name string

	// Path derived from route descriptor.
	Path string

	// CapPath contains the original Capstan-formatted path for this route.
	CapPath string

	// BasePath as indicated by the router. This is used by the URL builder but
	// may provide informational context to controllers indicating that this
	// route isn't mounted at the site root.
	BasePath string

	// CapBasePath is similar to BasePath with the exception that it contains
	// Capstan-formatted path information.
	CapBasePath string

	// MandatoryNoSlash strips any trailing slash from the route and creates a
	// single route with no trailing slash. This enforces the absense of a
	// slash. No redirection may occur from routes with a trailing slash to
	// routes without a slash when flagged with this feature.
	// Mandatory absense of a slash is enforced when the route is defined with a
	// trailing exclamation point, e.g. "/route!". Such routes may also include
	// a trailing slash to ensure the meaning is clearer (e.g. "not slash" or
	// "/route/!").
	MandatoryNoSlash bool

	// MandatorySlash is the precise opposite of MandatoryNoSlash: Routes are
	// required to terminate with a trailing slash and no redirection may occur
	// from routes without a slash.
	// Routes with a mandatory slash must terminate with a trailing slash, e.g.
	// "/route/".
	MandatorySlash bool

	// OptionalSlash creates two separate routing table entries: One with a
	// trailing slash and one without. If the route ends with a slash, this is
	// considered the route's default state, and requests to this route without
	// a trailing slash will be redirected to a route of the same name with the
	// slash appended. Likewise, the converse is true.
	// Optional slashes may be delineated with a terminating question mark, e.g.
	// "/route/?" for routes that will redirect to a trailing slash or "/route?"
	// for those that do not. The question mark itself is optional for routes
	// defined without a trailing slash and may be omitted, e.g., "/route" and
	// "/route?" define the same behavior. The question mark is advisable to
	// make clear the developer's intention, and may be required in some
	// contexts (such as defining the behavior of an index route).
	// Note: A trailing slash, e.g. "/route/" indicates that the route must
	// terminate with a *mandatory* slash. Hence, a terminating ? is required
	// when defining a default redirection state from "/route" to "/route/",
	// e.g. "/route/?".
	// This section will be clarified in the documentation.
	OptionalSlash bool

	// SlashIsDefault indicates that the default route state is to terminate
	// with a slash. The value of this flag is only applicable if OptionalSlash
	// is true.
	SlashIsDefault bool

	// RouteTimeout indicates this route should enforce a timeout of the
	// specified duration, in seconds. If ForceTimeout is true, the handler will
	// exit after RouteTimeout seconds. If ForceTimeout is false, then timeout
	// handling must be managed by the controller (and will be ignored
	// otherwise).
	RouteTimeout int

	// ForceTimeout will forcibly exit the handler after RouteTimeout seconds or
	// do nothing until the controller endpoint managed by this route exists of
	// its own volition.
	ForceTimeout bool

	// Paths for multiple routes that may be handled by the same controller.
	Paths map[string][]string

	// ContentType is a convenience mechanism for setting the content type of
	// the route if it is one of text/plain, text/json, or application/json. You
	// should use this instead of setting the headers directly.
	// This value is mostly intended for API endpoints that generate JSON
	// output.
	ContentType string

	// Headers used as route defaults.
	Headers http.Header

	// Prefix to prepend to the handler's name to limit naming collisions when
	// reverse-mapping URLs.
	Prefix string

	// Suffix to append to the handler's name. This will typically be the
	// request method but may be overridden here. If this value isn't set, the
	// request method is used instead.
	Suffix string

	// ParamTypes maps parameter names to their type for use by *Param() context
	// functions.
	ParamTypes map[string]string

	// Method associated with this route.
	Method string

	// Middleware for this route.
	// TODO: Eventually support redeclaration of middleware types such that it
	// accepts a Context. This will require also wrapping external middleware,
	// such as that which ships with chi and others.
	Middleware []func(http.Handler) http.Handler

	// Endpoint function.
	Endpoint Endpoint

	// Controller reference.
	Controller Controller

	// Upgrader for websocket connections.
	Upgrader *websocket.Upgrader

	// BeforeResponse call. If defined by the router, this function will be
	// called before any response is issued. If `error` contains a 400- or
	// 500-level error, the response is aborted.
	// This will be nil unless defined by the controller.
	BeforeResponse []func(Context, *Route) error

	// AfterResponse call. If defined by the router, this function will be
	// called after every response made to this route. If `error` contains a
	// 400- or 500-level error, its value is returned instead of the value
	// returned by the route's handler.
	// AfterResponse will also receive the error returned by Route.Endpoint.
	// This will be nil unless defined by the controller.
	AfterResponse []func(Context, error) error

	// Renderer defines a controller-specific renderer to use for this handler.
	// If this is nil, the global renderer will be used instead.
	Renderer render.Renderer
	// contains filtered or unexported fields

Route descriptor ultimately used for constructing chi routes. This encapsulates the actual user code handler and passes in the appropriate arguments.

func (*Route) Copy

func (rt *Route) Copy() *Route

Copy and return a new instance of the current route.

Beware: Non-value types are only copied as pointers to their original values. This means that maps local to the Route struct are not copied by value.

func (*Route) ForName

func (rt *Route) ForName() string

func (*Route) FullPath

func (rt *Route) FullPath() string

func (*Route) ServeHTTP

func (rt *Route) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP provides an HTTP handler implementation that makes routes compatible with Go's default HTTP server.

This function is somewhat messy and handles the entirety of Capstan's request handling logic. Refactoring is welcome.

func (*Route) WriteError

func (rt *Route) WriteError(ctx Context, err error)

type RouteFlag

type RouteFlag struct {
	Method   string
	Endpoint string

type RouteMap

type RouteMap struct {
	Method   string
	Endpoint Endpoint

RouteMap is currently unused. It will be includes as part of the Mapper() handler for controllers that define their own route map.

type Router

type Router struct {
	// contains filtered or unexported fields

func NewEmptyRouter

func NewEmptyRouter() *Router

func NewRouter

func NewRouter(app Application) *Router

func (*Router) AddListener

func (r *Router) AddListener(listener net.Listener)

AddListener accepts a listener against which the Chi handler will be attached and will be used as the base listener for an HTTP or HTTPS service.

This listener will be mapped to the configured network management as defined in network.go and netlisten_*.go. If the specified listener does not implement both net.Listen and syscall.Conn it will not be used for high availability graceful restart. If you depend on a custom listener, you may need to implement graceful restart yourself or implement syscall.Conn.

func (*Router) AfterResponseFunc

func (r *Router) AfterResponseFunc(fn func(Context, error) error)

AfterResponseFuncc configures a function to call after the response has been handled. Response data will have already been dispatched by the time this function is called; consequently, care should be taken not to manipulate the response.

func (*Router) AttachListener

func (r *Router) AttachListener(listener net.Listener)

AttachListener to the current route handler.

This may be used by external code to enable listeners.

func (*Router) AttachNamedListener

func (r *Router) AttachNamedListener(name string, listener net.Listener)

func (*Router) BeforeResponseFunc

func (r *Router) BeforeResponseFunc(fn func(Context, *Route) error)

BeforeResponseFunc configures a function to call before the response is about to be handled. This function must accept the route as its second argument. Errors returned by this function will, depending on their nature, prevent the route handler from being called.

func (*Router) Bind

func (r *Router) Bind(endpoint Controller) error

Bind the specified endpoint.

This method is the core of the router and handles all method routes directly and farms out other route types to separate functions (also located in this file). Bind() will also setup routes and map them.

The use of route.Copy() may appear confusing at first blush, but its purpose is to create a copy of (most of) the route and its data, which is then used to bind a method/endpoint tuple with go-chi. route.Copy() only performs a shallow copy; slicens and map pointers are replicate across all dependents.

func (*Router) Close

func (r *Router) Close()

Close all configured listeners gracefully. This calls Shutdown on each http.Server and waits until all connections have closed before terminating.

func (*Router) CloseNamed

func (r *Router) CloseNamed(name string) (err error)

CloseNamed listener.

This will gracefully shut down the named listener, if available. The special names "tls," "tcp," and "file" are used to close reserved listeners for TLS, TCP, and Unix domain socket traffic.

This will also remove the listener from the router's listeners store.

func (*Router) Group

func (r *Router) Group(path string) *RouterGroup

Group creates and returns a new router group.

func (*Router) HTTPError

func (r *Router) HTTPError(ctx Context)

func (*Router) HasSocket

func (r *Router) HasSocket() bool

HasSocket returns true if Capstan was configured to listen on a domain socket.

As with other Has* functions for listeners, this does not indicate a status for manually-configured listeners and applies only to those that were started via the Listen* methods (either automatically, via configuration, or manually).

func (*Router) HasTCP

func (r *Router) HasTCP() bool

HasTCP returns true if Capstan was configured to listen on a TCP socket.

As with other Has* functions for listeners, this does not indicate a status for manually-configured listeners and applies only to those that were started via the Listen* methods (either automatically, via configuration, or manually).

func (*Router) HasTLS

func (r *Router) HasTLS() bool

HasTLS returns true if Capstan was configured to listen on a TLS socket.

As with other Has* functions for listeners, this does not indicate a status for manually-configured listeners and applies only to those that were started via the Listen* methods (either automatically, via configuration, or manually).

func (*Router) Listen

func (r *Router) Listen() error

Listen on all configured listeners and wait until they close.

If an error is received by this function it will call Router.Close itself and begin the shutdown process.

func (*Router) ListenHTTP

func (r *Router) ListenHTTP(addr string) (net.Listener, error)

ListenHTTP allows client code to configure a new port to listen on. This should not be called if the server is already listening on an HTTP port. This is called internally if ListenAddress is set.

func (*Router) ListenSocket

func (r *Router) ListenSocket(sock string) (net.Listener, error)

ListenSocket allows client code to configure a new UNIX domain socket to listen on. This should not be called if the server is already listening on the same socket. This is called internally if ListenSocket is set.

func (*Router) ListenTLS

func (r *Router) ListenTLS(addr string) (net.Listener, error)

ListenTLS allows client code to configure a new TLS port to listen on. This should not be called if the server is already listening on a TLS port. This is called internally if ListenAddressTLS is set.

func (*Router) ManualBind

func (r *Router) ManualBind(method, path, suffix string, controller Controller, endpoint Endpoint)

ManualBind is used with Bind() routes to manually bind a given `endpoint` to the specified `path` with the HTTP request `method` and URLFor `suffix` provided. The controller must also be specified to correctly assemble the route.

func (*Router) Middleware

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

Middleware configures Router-global middleware for all routes bound to this Router.

func (*Router) Mux

func (r *Router) Mux() chi.Router

Mux returns the chi.Router mux associated with this Router instance.

func (*Router) ParseRoute

func (r *Router) ParseRoute(route string) *routeProps

ParseRoute processes the specified route, processes it, and returns a routeProps struct describing the route using go-chi syntax.

Route parsing is somewhat analogous to go-chi but uses a different syntax. In particular, route variables are delineated by "<" and ">" rather than "{" and "}" as per go-chi. Further, besides regex types, Capstan routes also define string, float, float32, float64, int, int32, and int64 types. Route syntax is:



Integer types:


Regular expressions:


func (*Router) Rebind

func (r *Router) Rebind() chi.Router

Rebind() incrementally rebinds all routes associated with this Router. This is useful when remapping a route's endpoint. A new muxer is returned with all the bindings set. This function should be used with the proxy Switch method.

When a Rebind is called, the routes are not immediately rebound. Instead, a new muxer is created with the same configuration already used by the existing muxer and all routes associated with this Router are bound, individually, to this muxer. Only when the routes have successfully been bound will the muxer be returned.

FIXME: This needs to work across subrouters as well.

func (*Router) ReplacePath

func (r *Router) ReplacePath(from, to string)

ReplacePath swaps a route endpoint for the route associated with `from` to the new endpoint `to`. Rebind is triggered if this call is successful.

This method also switches the proxy handler to the one returned by Rebind.

func (*Router) ReservedFunctions

func (r *Router) ReservedFunctions(reserved ...string)

func (*Router) ServeHTTP

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

func (*Router) SetProxy

func (r *Router) SetProxy(p ProxyHandler)

SetProxy changes the proxy for this router.

func (*Router) SetRenderer

func (r *Router) SetRenderer(renderer render.Renderer)

SetRender configures a global render.Renderer for all endpoints handled by this router. This may be overridden by renderer specified via the BaseController options for any given route. If this is never set, the Context.Render() becomes a noop and returns the noop implementation of Renderer.

func (*Router) SetupMuxer

func (r *Router) SetupMuxer()

func (*Router) Static

func (r *Router) Static(urlroot, path string)

Static binds the path described by `urlroot` to the filesystem `path` as a source for hosting static assets.

Being as this makes use of the Golang default http.FileServer implementation, it's worth considering a reverse proxy for better performance.

func (*Router) StaticVFS

func (r *Router) StaticVFS(urlroot, path string, fs vfs.FileSystem)

Static binds the path described by `urlroot` to the filesystem `path` as contained in the virtual filesystem implementation `fs` as a source for hosting static assets. This should work with any VFS implementation compatible with vfs.FileSystem but is primarily intended to work with Embedder.

Being as this makes use of the Golang default http.FileServer implementation, it's worth considering a reverse proxy for better performance.

func (*Router) URLs

func (r *Router) URLs() *URLMapper

URLs retrieves the Router's configured URLMapper.

func (*Router) Unmount

func (r *Router) Unmount(path string)

Unmount removes the route associated with `path` from the router. This calls Rebind if successful.

This method also switches the proxy handler to the one returned by Rebind.

type RouterGroup

type RouterGroup struct {
	// contains filtered or unexported fields

func NewRouterGroup

func NewRouterGroup(path string, parent *Router) *RouterGroup

func (*RouterGroup) Add

func (rg *RouterGroup) Add(fn func(*Router))

func (*RouterGroup) Header

func (rg *RouterGroup) Header() http.Header

func (*RouterGroup) Middleware

func (rg *RouterGroup) Middleware(middleware chi.Middlewares)

func (*RouterGroup) Name

func (rg *RouterGroup) Name(name string) *RouterGroup

func (*RouterGroup) Options

func (rg *RouterGroup) Options() *RouterOptions

func (*RouterGroup) Rebase

func (rg *RouterGroup) Rebase(path string)

func (*RouterGroup) Rebind

func (rg *RouterGroup) Rebind() chi.Router

func (*RouterGroup) RebindSelf

func (rg *RouterGroup) RebindSelf()

func (*RouterGroup) ReplacePath

func (rg *RouterGroup) ReplacePath(from, to string)

func (*RouterGroup) WithRenderer

func (rg *RouterGroup) WithRenderer(renderer render.Renderer) *RouterGroup

type RouterOptions

type RouterOptions struct {
	ContentType string

type ServerConfig

type ServerConfig = config.ServerConfig

ServerConfig is the top-level pseudo-alias for Capstan's server configuration. This is a convenience type to reduce imports.

type SessionConfig

type SessionConfig = config.SessionConfig

SessionConfig is a top-level pseudo-alas for Capstan's session configuration.

type ShutdownHook

type ShutdownHook func() error

ShutdownHook types are registered to be called whenever the application is terminated normally.

type TraceHandler

type TraceHandler interface {
	Trace(Context) error

type URLBuilder

type URLBuilder struct {
	External bool
	Scheme   string
	Host     string
	// contains filtered or unexported fields

func (*URLBuilder) Asset

func (b *URLBuilder) Asset(asset string)

func (*URLBuilder) Encode

func (b *URLBuilder) Encode() string

func (*URLBuilder) Param

func (b *URLBuilder) Param(name, value string) *URLBuilder

Param attaches a parameter to the internal parameters map. Parameters that are named in the URL pathspec will be expanded as path components; others will be treated as query string parameters.

func (*URLBuilder) Params

func (b *URLBuilder) Params(params url.Values) *URLBuilder

Params overwrites the internal parameters map with the one specified. Parameters that are named in the URL pathspec will be expanded as path components; others will be treated as query string parameters.

func (*URLBuilder) SetQuery

func (b *URLBuilder) SetQuery(query string) error

type URLMapper

type URLMapper struct {
	Config  *config.ServerConfig
	Routes  map[string]*Route
	Domains map[string]*URLMapper
	Static  string
	// contains filtered or unexported fields

func NewURLMapper

func NewURLMapper(conf *config.ServerConfig) *URLMapper

NewURLMapper returns a new URLMapper configured to use the specified config. We use a pointer to config.Config as some changes to URL behavior may be set dynamically depending on how the application is running. For example, enabling just HTTP or TLS will switch the protocol scheme between "http" and "https," respectively, or enabling both will remove the scheme entirely and use "relative" protocols (e.g. "//").

func (*URLMapper) For

func (u *URLMapper) For(name string) *URLBuilder

func (*URLMapper) Has

func (u *URLMapper) Has(route *Route) bool

func (*URLMapper) Map

func (u *URLMapper) Map(route *Route)

func (*URLMapper) Remove

func (u *URLMapper) Remove(route *Route)

type VFS

type VFS interface {

type VFSFileSystem

type VFSFileSystem struct {

type VFSFilebox

type VFSFilebox struct {

type VFSPassThrough

type VFSPassThrough struct {

type VFSRegistry

type VFSRegistry struct {
	Registry map[string][]VFS
	// contains filtered or unexported fields

VFSRegistry works by storing available virtual file systems and a series of upgrade/downgrade listeners. As a new VFS is added as an upgrade, metadata related to it is passed to all registered upgraders which may then elect to utilize the new VFS (or not). If an error or panic occurs when attempting to access a VFS, the downgrade callbacks are triggered for that VFS automatically and the VFS reverts to its prior state.

As an example, assume you have an application that is distributed with migration scripts for a database embedded into the binary. The VFS, by default, will utilize these migrations by default. However, also assume that you provide migration upgrades that can occur out-of-band from the binary. When you distribute these upgrades, your application can instruct the VFSRegistry to upgrade the migrations listener, which will pass along another VFS instance that reads from the updated .zip. This may be configured as a passthrough VFS that will first attempt to read files from the .zip and then fall back to those integrated into the binary.

Another example: Assume you download a new theme that extends one of the core templates distributed with your binary. You need access to both the new theme's .zip and the integrated templates; you can have a VFS passthrough that will read from both the .zip and the built-in theme separately, allowing you to upgrade the new theme with add on .zips. If a new add on .zip doesn't work to your liking, you could remove it, and when the VFS layer panics from the missing file, it will downgrade itself until it either reverts to one of the previous .zip files ( to, for example) or until it reverts to reading from the binary directly.

Alternatively, you may also set up priorities such that files that exist in the current working directory can override those contained in archives or vice-versa.

func (*VFSRegistry) OnDowngrade

func (r *VFSRegistry) OnDowngrade(fn downgradeFunc, passthrough bool)

func (*VFSRegistry) OnUpgrade

func (r *VFSRegistry) OnUpgrade(fn upgradeFunc, passthrough bool)

type VFSZipFile

type VFSZipFile struct {

type WebSocketHandler

type WebSocketHandler interface {
	WebSocket(Context) error

Package Files

  • api.go
  • application.go
  • context.go
  • extension.go
  • funcs.go
  • http.go
  • netlisten_unix.go
  • network.go
  • network_unix.go
  • proxy.go
  • route.go
  • router.go
  • router_bind.go
  • router_listen.go
  • router_private.go
  • router_trie.go
  • router_utils.go
  • routergroup.go
  • service.go
  • trie.go
  • types.go
  • urls.go
  • vfs.go
Documentation was rendered with GOOS=linux and GOARCH=amd64.

Jump to identifier

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to identifier