goji.io: goji.io Index | Files | Directories

package goji

import "goji.io"

Package goji is a minimalistic and flexible HTTP request multiplexer.

Goji itself has very few features: it is first and foremost a standard set of interfaces for writing web applications. Several subpackages are distributed with Goji to provide standard production-ready implementations of several of the interfaces, however users are also encouraged to implement the interfaces on their own, especially if their needs are unusual.


Package Files

dispatch.go goji.go handle.go middleware.go mux.go pattern.go router.go router_trie.go

type Mux Uses

type Mux struct {
    // contains filtered or unexported fields

Mux is a HTTP multiplexer / router similar to net/http.ServeMux.

Muxes multiplex traffic between many http.Handlers by selecting the first applicable Pattern. They then call a common middleware stack, finally passing control to the selected http.Handler. See the documentation on the Handle function for more information about how routing is performed, the documentation on the Pattern type for more information about request matching, and the documentation for the Use method for more about middleware.

Muxes cannot be configured concurrently from multiple goroutines, nor can they be configured concurrently with requests.

func NewMux Uses

func NewMux() *Mux

NewMux returns a new Mux with no configured middleware or routes.

func SubMux Uses

func SubMux() *Mux

SubMux returns a new Mux with no configured middleware or routes, and which inherits routing information from the passed context. This is especially useful when using one Mux as a http.Handler registered to another "parent" Mux.

For example, a common pattern is to organize applications in a way that mirrors the structure of its URLs: a photo-sharing site might have URLs that start with "/users/" and URLs that start with "/albums/", and might be organized using three Muxes:

root := NewMux()
users := SubMux()
root.Handle(pat.New("/users/*"), users)
albums := SubMux()
root.Handle(pat.New("/albums/*"), albums)

// e.g., GET /users/carl
users.Handle(pat.Get("/:name"), renderProfile)
// e.g., POST /albums/
albums.Handle(pat.Post("/"), newAlbum)

func (*Mux) Handle Uses

func (m *Mux) Handle(p Pattern, h http.Handler)

Handle adds a new route to the Mux. Requests that match the given Pattern will be dispatched to the given http.Handler.

Routing is performed in the order in which routes are added: the first route with a matching Pattern will be used. In particular, Goji guarantees that routing is performed in a manner that is indistinguishable from the following algorithm:

// Assume routes is a slice that every call to Handle appends to
for _, route := range routes {
	// For performance, Patterns can opt out of this call to Match.
	// See the documentation for Pattern for more.
	if r2 := route.pattern.Match(r); r2 != nil {
		route.handler.ServeHTTP(w, r2)

It is not safe to concurrently register routes from multiple goroutines, or to register routes concurrently with requests.

func (*Mux) HandleFunc Uses

func (m *Mux) HandleFunc(p Pattern, h func(http.ResponseWriter, *http.Request))

HandleFunc adds a new route to the Mux. It is equivalent to calling Handle on a handler wrapped with http.HandlerFunc, and is provided only for convenience.

func (*Mux) ServeHTTP Uses

func (m *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements net/http.Handler.

func (*Mux) Use Uses

func (m *Mux) Use(middleware func(http.Handler) http.Handler)

Use appends a middleware to the Mux's middleware stack.

Middleware are composable pieces of functionality that augment http.Handlers. Common examples of middleware include request loggers, authentication checkers, and metrics gatherers.

Middleware are evaluated in the reverse order in which they were added, but the resulting http.Handlers execute in "normal" order (i.e., the http.Handler returned by the first Middleware to be added gets called first).

For instance, given middleware A, B, and C, added in that order, Goji will behave similarly to this snippet:

augmentedHandler := A(B(C(yourHandler)))
augmentedHandler.ServeHTTP(w, r)

Assuming each of A, B, and C look something like this:

func A(inner http.Handler) http.Handler {
	log.Print("A: called")
	mw := func(w http.ResponseWriter, r *http.Request) {
		log.Print("A: before")
		inner.ServeHTTP(w, r)
		log.Print("A: after")
	return http.HandlerFunc(mw)

we'd expect to see the following in the log:

C: called
B: called
A: called
A: before
B: before
C: before
yourHandler: called
C: after
B: after
A: after

Note that augmentedHandler will called many times, producing the log output below the divider, while the outer middleware functions (the log output above the divider) will only be called a handful of times at application boot.

Middleware in Goji is called after routing has been performed. Therefore it is possible to examine any routing information placed into the Request context by Patterns, or to view or modify the http.Handler that will be routed to. Middleware authors should read the documentation for the "middleware" subpackage for more information about how this is done.

The http.Handler returned by the given middleware must be safe for concurrent use by multiple goroutines. It is not safe to concurrently register middleware from multiple goroutines, or to register middleware concurrently with requests.

type Pattern Uses

type Pattern interface {
    // Match examines the input Request to determine if it matches some
    // criteria, and if so returns a non-nil output Request. This returned
    // Request will be passed to the middleware stack and the final Handler.
    // Patterns often extract variables from the Request, for instance from
    // the URL or from HTTP headers. In this case, it is common for the
    // Request returned from the Match function to be derived from the input
    // Request using the WithContext function, with a Context that contains
    // those variable bindings. If no variable bindings are necessary,
    // another common choice is to return the input Request unchanged.
    // Match must not mutate the passed request if it returns nil.
    // Implementers are also strongly discouraged from mutating the input
    // Request even in the event of a match; instead, prefer making a copy.
    Match(*http.Request) *http.Request

Pattern determines whether a given request matches some criteria. Goji users looking for a concrete type that implements this interface should consider Goji's "pat" sub-package, which implements a small domain specific language for HTTP routing.

Patterns typically only examine a small portion of incoming requests, most commonly the HTTP method and the URL's RawPath. As an optimization, Goji can elide calls to your Pattern for requests it knows cannot match. Pattern authors who wish to take advantage of this functionality (and in some cases an asymptotic performance improvement) can augment their Pattern implementations with any of the following methods:

// HTTPMethods returns a set of HTTP methods that this Pattern matches,
// or nil if it's not possible to determine which HTTP methods might be
// matched. Put another way, requests with HTTP methods not in the
// returned set are guaranteed to never match this Pattern.
HTTPMethods() map[string]struct{}

// PathPrefix returns a string which all RawPaths that match this
// Pattern must have as a prefix. Put another way, requests with
// RawPaths that do not contain the returned string as a prefix are
// guaranteed to never match this Pattern.
PathPrefix() string

The presence or lack of these performance improvements should be viewed as an implementation detail and are not part of Goji's API compatibility guarantee. It is the responsibility of Pattern authors to ensure that their Match function always returns correct results, even if these optimizations are not performed.

All operations on Patterns must be safe for concurrent use by multiple goroutines.


internalPackage internal is a private package that allows Goji to expose a less confusing interface to its users.
middlewarePackage middleware contains utilities for Goji Middleware authors.
patPackage pat is a URL-matching domain-specific language for Goji.
patternPackage pattern contains utilities for Goji Pattern authors.

Package goji imports 5 packages (graph) and is imported by 191 packages. Updated 2021-01-07. Refresh now. Tools for package owners.