Capstan is a Golang web framework that shares some similarities with others in its segment.
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
Benjamin Shelton 5b5ef236ff Register termination of watchers on application shutdown. pirms 1 nedēļas
auth Replaced KeyStar references with cryptohelper, which has been split out pirms 5 mēnešiem
cmd/demos Breaking change: Top-level config is now required. pirms 4 mēnešiem
config Added comments clarifying certain behaviors when using multiapp mode. pirms 4 mēnešiem
docs Added extra skeleton files for other topics. pirms 3 mēnešiem
errors Added application-specific errors. pirms 4 mēnešiem
extension Register termination of watchers on application shutdown. pirms 1 nedēļas
fixtures/templates Added zipped fixture. pirms 1 gada
internal Updated/added comments. pirms 4 mēnešiem
mappers Re-homed project and most declared dependencies. pirms 10 mēnešiem
middleware Application is now an interface. pirms 6 mēnešiem
render Added TODO notes for theme support and correct VFS for theming. See pirms 8 mēnešiem
session Replaced KeyStar references with cryptohelper, which has been split out pirms 5 mēnešiem
status Re-homed project and most declared dependencies. pirms 10 mēnešiem
tests Added sub-subapp unit tests. pirms 3 mēnešiem
utils More contemplation. pirms 9 mēnešiem
vfs Re-homed project and most declared dependencies. pirms 10 mēnešiem
.gitignore Ignore any .pid files generated by test binaries. pirms 1 gada
LICENSE New year. pirms 11 mēnešiem
Makefile Added benchmark options for convenience. pirms 4 mēnešiem My brain's autocorrect doesn't work. pirms 2 mēnešiem
api.go Application API updated to include Application, for raw application type pirms 3 mēnešiem
application.go Implement additions to API and support attaching sub-subapplications. pirms 3 mēnešiem
capstan_test.go Split integration tests into their own files and outside of root. pirms 1 gada
context.go Okay, the actual underlying mistake was pretty stupid, which made it pirms 8 mēnešiem
extension.go Added deinitialization interface. pirms 3 nedēļām
funcs.go Actually honor the BasePath configuration. pirms 10 mēnešiem
go.mod Updated VFS dependency. pirms 3 mēnešiem
go.sum Dependency updates. pirms 1 gada
http.go Moved routing files into base package. pirms 11 mēnešiem
netlisten_unix.go Wrap direct access in function calls to gate internal API behavior for pirms 3 mēnešiem
netlisten_windows.go Moved routing files into base package. pirms 11 mēnešiem
network.go Socket management types include given address -> real address mappers pirms 3 mēnešiem
network_unix.go Moved routing files into base package. pirms 11 mēnešiem
network_windows.go Moved routing files into base package. pirms 11 mēnešiem
package_test.go Added setup code for package-level tests. pirms 4 mēnešiem
proxy.go Multiple calls to AddApplicationHandler via the radixLoader now calls pirms 3 mēnešiem
route.go Log context errors if present. pirms 8 mēnešiem
router.go Added Proxy() convenience method. pirms 3 mēnešiem
router_bind.go BaseController.Path is now mandatory. pirms 4 mēnešiem
router_listen.go Actually return errors. pirms 3 mēnešiem
router_private.go Breaking change: Top-level config is now required. pirms 4 mēnešiem
router_trie.go Moved routing files into base package. pirms 11 mēnešiem
router_utils.go Moved routing files into base package. pirms 11 mēnešiem
routergroup.go Actually honor the BasePath configuration. pirms 10 mēnešiem
service.go Serialize given -> real addr mapping. pirms 3 mēnešiem
trie.go Added Overwrite method. pirms 3 mēnešiem
trie_test.go Renamed node types away from temporary assignments. pirms 4 mēnešiem
types.go Import top-level types. pirms 4 mēnešiem
urls.go Use calculated config members. pirms 4 mēnešiem
urls_test.go Re-homed project and most declared dependencies. pirms 10 mēnešiem
vfs.go Moved routing files into base package. pirms 11 mēnešiem

Capstan: A Convenience Framework for Golang

Capstan is a framework that aims to simplify complex use cases that reach beyond basic HTTP handlers, such as dependency management, and reduces the amount of code required as handlers grow and evolve beyond what is possible with the standard library. It provides helpers for common (and not so common) tasks, including graceful shutdowns, rebinding mount points, and more. Capstan uses go-chi for its route muxer. Philosophically, Capstan is inspired in part by Flask and Flask-Classy.

Capstan is not for you if you require handlers that retain compatibility with net/http. Though this could (and arguably should) be rememdied by using the context package, there are no plans currently to reimplement Capstan in this fashion. Be ware! The Capstan API may appear simple at first blush, but it has a depth and complexity that may not be viable for all projects. If you need a simple API server, consider using go-chi directly.

Bear in mind that the project is still very much in its infancy, and APIs are subject to change. There are numerous rough patches and sharp objects in the code.


Capstan's implementation comprises these features (and some anti-features):

  • Controller-centric MVC. At present, it's largely “VC” as there is no defined model implementation. Capstan is very much “bring your own model.”
  • Requests are designed to call method-named functions per controller per path. This means that individual functions are named after and define an HTTP verb, such as Get or Post. Controllers therefore should be highly focused to a single endpoint. (This isn't strictly necessary; see below.)
  • Custom methods can be defined by implementing either the Binder interface, MapperHandler interface (work-in-progress), or by naming functions according to the pattern <Method><Name><SlashState>. This will become clearer later in the documentation once it's written.
  • Multiple renderers are supported through the Templater interface. We primarily encourage the use of pongo2 but provide wrappers for Go's built in template rendering library. (Note: Using anything but pongo2 may limit features available to templates, and using multiple template types in a single project will present unique challenges and difficulties that, while not insurmountable, are unnecessary and will be frought with sleepless nights.)
  • Renderers may be defined globally or per-controller. If a renderer is defined globally, all controller bindings that don't define a renderer will use the global one by default.
  • Capstan's pongo2 wrappers can make use of our VFS layer that integrates with Embedder for embedding assets into the compiled binary. The template engine is therefore capable of reading templates and other assets directly from disk or the binary itself. ZIP files are also supported. When combined with VFS, it's possible to layer reads from multiple sources (e.g. the binary, a ZIP file, or the file system).
  • Built-in TLS configuration helpers are provided. ACME support is a work in progress which will allow use of services like Let's Encrypt.
  • Capstan can listen on Unix sockets for use with local front end proxies like nginx or HAProxy. Doing so does not provide noticeable performance improvements over using TCP sockets.
  • Supports remapping endpoints (called “rebinding” in Capstan parlance) without restarting the service. Endpoints may be deleted (Router.Unmount) or renamed (Router.ReplacePath).
  • Optional websocket endpoint handlers as part of the controller semantics.
  • Graceful shutdown and in-place replacement/restart for seamless upgrades. Not presently supported on Windows and likely never will be.
  • URL mapper that exposes URL resolution for templates. In pongo2, this is provided via the functions url() and external(). URLs are typically mapped as [<prefix>.]<name>.<suffix>; for example, if you have a controller IndexController and were accessing its Get method, you would retrieve the mapped URL by calling url("IndexController:get"). Custom url() binding is provided by Router.ManualBind. The <prefix> is dictated by router groups or through manual declaration at controller bind time. Naming conflicts can be resolved during controller initialization manually, by providing a symbolic name for the controller, or automatically through a numeric suffix (e.g. IndexController2).
  • Trailing slashes can be controlled via the ?, ! or + syntax. ? indicates a trailing slash is optional. ! indicates a trailing slash must not be provided (and a 404 is generated). + indicates a trailing slash is mandatory for subroute declarations (but is typically unnecessary). Otherwise, if a route is declared with a trailing slash it is considered mandatory and requests made without the trailing slash will result in a 404. Optional slashes (indicated by a trailing ?) can either have a slash-provided or slash-absent default state; if a ? is immediately preceded by a slash, e.g. /?, a redirection route will be created that directs requests minus the trailing slash to a route that has the trailing slash appended. Likewise, if there is no slash preceding the ?, the redirection route will direct requests with a trailing / to the route without it. You should use optional slash routes sparingly since this does necessitate the generation of (potentially) superfluous routes.
  • Typed route variables. This requires a syntax differing slightly from go-chi. Type enforcement is not presently implemented (but likely will be). We use < and > to delineate route variables and deliberately introduce incompatibilities with go-chi to prevent confusion. Variable types are declared with a :<type> suffix, e.g. /path/<name:string>, which would create a parameterized variable of the name name and type string. Regex is passed through to go-chi.
  • Route groups wrap go-chi's groups and provide methods namespacing them from other routes both for url() template function(s) and for isolation.
  • Supports any middleware supported by go-chi and provides slight modifications for middleware supplied by go-chi (such as supporting the NO_COLOR envvar for go-chi's logger).
  • Supports before and after response bindings for cases where middleware may be too low level and where the route context needs to be fully configured prior to or after handling the endpoint.
  • Custom error page support, with context helpers.
  • Extension support that includes a few out-of-the-box extensions, such as CSRF protection and session management. Authentication support is forthcoming.
  • Fully-featured dependency injection.
  • Limited support for privilege reduction; e.g., setting Capstan's RunAs configuration option and running initially as the root user will provoke Capstan into first binding to its configured ports then dropping privileges. This is useful for listening on lower ports, such as port 80 and 443, and although Capstan is fully capable of doing so, it is advisable to use reverse proxies in front of a Capstan application.
  • Open port scanner for automatically picking open ports. Useful for writing installers that need to find a free port in order to start a visual browser-based installer.
  • Multiple application support for running multiple instances of Capstan applications under the same Capstan instance. It's Capstans all the way down!
  • Additional utilities. See the utils subpackage.

Sample Application

package main

import (

type IndexController struct {
    Server capstan.Server `inject:"app"`

func (c *IndexController) Index(ctx capstan.Context) error {
    return ctx.Write([]byte("Hello! Listening on address: "+c.Server.Config().ListenAddress))

func main() {
    app := capstan.New(&capstan.ServerConfig{
        ListenAddress: ":8080",

        BaseController: capstan.BaseController{
            Path: "/",



The Capstan source distribution contains documentation under the docs/ subdirectory. Presently, this documentation is somewhat sparse but the file contains a beginner's guide adequate enough to get started. There is also a small but mostly complete discussion on Capstan's dependency injection framework.


Capstan is licensed under the fairly liberal and highly permissive NCSA license. We prefer this license as it combines the best of BSD and MIT licenses while also providing coverage for associated documentation and other works that are not strictly considered original source code. Consequently, all Capstan documentation is likewise covered under the same license as the codebase itself.

As with BSD-like licenses, attribution is, of course, required.