goji

package module
v2.0.2+incompatible Latest Latest
Warning

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

Go to latest
Published: Jan 26, 2019 License: MIT Imports: 5 Imported by: 576

README

Goji

GoDoc Build Status

Goji is a HTTP request multiplexer, similar to net/http.ServeMux. It compares incoming requests to a list of registered Patterns, and dispatches to the http.Handler that corresponds to the first matching Pattern. Goji also supports Middleware (composable shared functionality applied to every request) and uses the standard context package to store request-scoped values.

Quick Start

package main

import (
        "fmt"
        "net/http"

        "goji.io"
        "goji.io/pat"
)

func hello(w http.ResponseWriter, r *http.Request) {
        name := pat.Param(r, "name")
        fmt.Fprintf(w, "Hello, %s!", name)
}

func main() {
        mux := goji.NewMux()
        mux.HandleFunc(pat.Get("/hello/:name"), hello)

        http.ListenAndServe("localhost:8000", mux)
}

Please refer to Goji's GoDoc Documentation for a full API reference.

Stability

Goji's API was recently updated to use the new net/http and context integration, and is therefore some of its interfaces are in a state of flux. We don't expect any further changes to the API, and expect to be able to announce API stability soon. Goji is suitable for use in production.

Prior to Go 1.7, Goji promised API stability with a different API to the one that is offered today. The author broke this promise, and does not take this breach of trust lightly. While stability is obviously extremely important, the author and community have decided to follow the broader Go community in standardizing on the standard library copy of the context package.

Users of the old API can find that familiar API on the net-context branch. The author promises to maintain both the net-context branch and master for the forseeable future.

Community / Contributing

Goji maintains a mailing list, gojiberries, where you should feel welcome to ask questions about the project (no matter how simple!), to announce projects or libraries built on top of Goji, or to talk about Goji more generally. Goji's author (Carl Jackson) also loves to hear from users directly at his personal email address, which is available on his GitHub profile page.

Contributions to Goji are welcome, however please be advised that due to Goji's stability guarantees interface changes are unlikely to be accepted.

All interactions in the Goji community will be held to the high standard of the broader Go community's Code of Conduct.

Documentation

Overview

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.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Mux

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

func NewMux() *Mux

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

func SubMux

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

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)
		break
	}
}

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

func (*Mux) HandleFunc

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

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

ServeHTTP implements net/http.Handler.

func (*Mux) Use

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

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.

Directories

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

Jump to

Keyboard shortcuts

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