web

package
v0.0.0-...-90d355d Latest Latest
Warning

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

Go to latest
Published: Sep 1, 2014 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package web implements a fast and flexible middleware stack and mux.

The underlying philosophy behind this package is that net/http is a very good HTTP library which is only missing a few features. If you disagree with this statement (e.g., you think that the interfaces it exposes are not especially good, or if you're looking for a comprehensive "batteries included" feature list), you're likely not going to have a good time using this library. In that spirit, we have attempted wherever possible to be compatible with net/http. You should be able to insert any net/http compliant handler into this library, or use this library with any other net/http compliant mux.

This package attempts to solve three problems that net/http does not. First, it allows you to specify URL patterns with Sinatra-like named wildcards and regexps. Second, it allows you to write reconfigurable middleware stacks. And finally, it allows you to attach additional context to requests, in a manner that can be manipulated by both compliant middleware and handlers.

A usage example:

m := web.New()

Use your favorite HTTP verbs:

var legacyFooHttpHandler http.Handler // From elsewhere
m.Get("/foo", legacyFooHttpHandler)
m.Post("/bar", func(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("Hello world!"))
})

Bind parameters using either Sinatra-like patterns or regular expressions:

m.Get("/hello/:name", func(c web.C, w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, %s!", c.URLParams["name"])
})
pattern := regexp.MustCompile(`^/ip/(?P<ip>(?:\d{1,3}\.){3}\d{1,3})$`)
m.Get(pattern, func(c web.C, w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Info for IP address %s:", c.URLParams["ip"])
})

Middleware are functions that wrap http.Handlers, just like you'd use with raw net/http. Middleware functions can optionally take a context parameter, which will be threaded throughout the middleware stack and to the final handler, even if not all of these things support contexts. Middleware are encouraged to use the Env parameter to pass data to other middleware and to the final handler:

m.Use(func(h http.Handler) http.Handler {
	handler := func(w http.ResponseWriter, r *http.Request) {
		log.Println("Before request")
		h.ServeHTTP(w, r)
		log.Println("After request")
	}
	return http.HandlerFunc(handler)
})
m.Use(func(c *web.C, h http.Handler) http.Handler {
	handler := func(w http.ResponseWriter, r *http.Request) {
		cookie, err := r.Cookie("user")
		if err == nil {
			// Consider using the middleware EnvInit instead
			// of repeating the below check
			if c.Env == nil {
				c.Env = make(map[string]interface{})
			}
			c.Env["user"] = cookie.Value
		}
		h.ServeHTTP(w, r)
	}
	return http.HandlerFunc(handler)
})

m.Get("/baz", func(c web.C, w http.ResponseWriter, r *http.Request) {
	if user, ok := c.Env["user"].(string); ok {
		w.Write([]byte("Hello " + user))
	} else {
		w.Write([]byte("Hello Stranger!"))
	}
})

Index

Constants

View Source
const ValidMethodsKey = "goji.web.validMethods"

The key used to communicate to the NotFound handler what methods would have been allowed if they'd been provided.

Variables

This section is empty.

Functions

This section is empty.

Types

type C

type C struct {
	// The parameters parsed by the mux from the URL itself. In most cases,
	// will contain a map from programmer-specified identifiers to the
	// strings that matched those identifiers, but if a unnamed regex
	// capture is used, it will be assigned to the special identifiers "$1",
	// "$2", etc.
	URLParams map[string]string
	// A free-form environment, similar to Rack or PEP 333's environments.
	// Middleware layers are encouraged to pass data to downstream layers
	// and other handlers using this map, and are even more strongly
	// encouraged to document and maybe namespace the keys they use.
	Env map[string]interface{}
}

C is a per-request context object which is threaded through all compliant middleware layers and to the final request handler.

As an implementation detail, references to these structs are reused between requests to reduce allocation churn, but the maps they contain are created fresh on every request. If you are closing over a context (especially relevant for middleware), you should not close over either the URLParams or Env objects, instead accessing them through the context whenever they are required.

type Handler

type Handler interface {
	http.Handler
	ServeHTTPC(C, http.ResponseWriter, *http.Request)
}

Handler is a superset of net/http's http.Handler, which also includes a mechanism for serving requests with a context. If your handler does not support the use of contexts, we encourage you to use http.Handler instead.

type HandlerFunc

type HandlerFunc func(C, http.ResponseWriter, *http.Request)

HandlerFunc is like net/http's http.HandlerFunc, but supports a context object. Implements both http.Handler and web.Handler free of charge.

func (HandlerFunc) ServeHTTP

func (h HandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request)

func (HandlerFunc) ServeHTTPC

func (h HandlerFunc) ServeHTTPC(c C, w http.ResponseWriter, r *http.Request)

ServeHTTPC wraps ServeHTTP with a context parameter.

type Mux

type Mux struct {
	// contains filtered or unexported fields
}

Mux is an HTTP multiplexer, much like net/http's ServeMux.

Routes may be added using any of the various HTTP-method-specific functions. When processing a request, when iterating in insertion order the first route that matches both the request's path and method is used.

There are two other differences worth mentioning between web.Mux and http.ServeMux. First, string patterns (i.e., Sinatra-like patterns) must match exactly: the "rooted subtree" behavior of ServeMux is not implemented. Secondly, unlike ServeMux, Mux does not support Host-specific patterns.

If you require any of these features, remember that you are free to mix and match muxes at any part of the stack.

In order to provide a sane API, many functions on Mux take interface{}'s. This is obviously not a very satisfying solution, but it's probably the best we can do for now. Instead of duplicating documentation on each method, the types accepted by those functions are documented here.

A middleware (the untyped parameter in Use() and Insert()) must be one of the following types:

  • func(http.Handler) http.Handler
  • func(c *web.C, http.Handler) http.Handler

All of the route-adding functions on Mux take two untyped parameters: pattern and handler. Pattern must be one of the following types:

  • string. It will be interpreted as a Sinatra-like pattern. In particular, the following syntax is recognized:
  • a path segment starting with with a colon will match any string placed at that position. e.g., "/:name" will match "/carl", binding "name" to "carl".
  • a pattern ending with an asterisk will match any prefix of that route. For instance, "/admin/*" will match "/admin/" and "/admin/secret/lair". This is similar to Sinatra's wildcard, but may only appear at the very end of the string and is therefore significantly less powerful.
  • regexp.Regexp. The library assumes that it is a Perl-style regexp that is anchored on the left (i.e., the beginning of the string). If your regexp is not anchored on the left, a hopefully-identical left-anchored regexp will be created and used instead.
  • web.Pattern

Handler must be one of the following types:

  • http.Handler
  • web.Handler
  • func(w http.ResponseWriter, r *http.Request)
  • func(c web.C, w http.ResponseWriter, r *http.Request)

func New

func New() *Mux

New creates a new Mux without any routes or middleware.

func (*Mux) Abandon

func (m *Mux) Abandon(middleware interface{}) error

Remove the given middleware from the middleware stack. Returns an error if no such middleware can be found.

If the name of the middleware to delete is ambiguous, the first (outermost) one is chosen. It is illegal to call this function concurrently with active requests.

func (*Mux) Compile

func (rt *Mux) Compile() *routeMachine

Compile the list of routes into bytecode. This only needs to be done once after all the routes have been added, and will be called automatically for you (at some performance cost on the first request) if you do not call it explicitly.

func (*Mux) Connect

func (rt *Mux) Connect(pattern interface{}, handler interface{})

Dispatch to the given handler when the pattern matches and the HTTP method is CONNECT. See the documentation for type Mux for a description of what types are accepted for pattern and handler.

func (*Mux) Delete

func (rt *Mux) Delete(pattern interface{}, handler interface{})

Dispatch to the given handler when the pattern matches and the HTTP method is DELETE. See the documentation for type Mux for a description of what types are accepted for pattern and handler.

func (*Mux) Get

func (rt *Mux) Get(pattern interface{}, handler interface{})

Dispatch to the given handler when the pattern matches and the HTTP method is GET. See the documentation for type Mux for a description of what types are accepted for pattern and handler.

All GET handlers also transparently serve HEAD requests, since net/http will take care of all the fiddly bits for you. If you wish to provide an alternate implementation of HEAD, you should add a handler explicitly and place it above your GET handler.

func (*Mux) Handle

func (rt *Mux) Handle(pattern interface{}, handler interface{})

Dispatch to the given handler when the pattern matches, regardless of HTTP method. See the documentation for type Mux for a description of what types are accepted for pattern and handler.

This method is commonly used to implement sub-routing: an admin application, for instance, can expose a single handler that is attached to the main Mux by calling Handle("/admin*", adminHandler) or similar. Note that this function doesn't strip this prefix from the path before forwarding it on (e.g., the handler will see the full path, including the "/admin" part), but this functionality can easily be performed by an extra middleware layer.

func (*Mux) Head

func (rt *Mux) Head(pattern interface{}, handler interface{})

Dispatch to the given handler when the pattern matches and the HTTP method is HEAD. See the documentation for type Mux for a description of what types are accepted for pattern and handler.

func (*Mux) Insert

func (m *Mux) Insert(middleware, before interface{}) error

Insert the given middleware immediately before a given existing middleware in the stack. See the documentation for type Mux for a list of valid middleware types. Returns an error if no middleware has the name given by "before."

No attempt is made to enforce the uniqueness of middlewares. If the insertion point is ambiguous, the first (outermost) one is chosen. It is illegal to call this function concurrently with active requests.

func (*Mux) NotFound

func (rt *Mux) NotFound(handler interface{})

Set the fallback (i.e., 404) handler for this mux. See the documentation for type Mux for a description of what types are accepted for handler.

As a convenience, the context environment variable "goji.web.validMethods" (also available as the constant ValidMethodsKey) will be set to the list of HTTP methods that could have been routed had they been provided on an otherwise identical request.

func (*Mux) Options

func (rt *Mux) Options(pattern interface{}, handler interface{})

Dispatch to the given handler when the pattern matches and the HTTP method is OPTIONS. See the documentation for type Mux for a description of what types are accepted for pattern and handler.

func (*Mux) Patch

func (rt *Mux) Patch(pattern interface{}, handler interface{})

Dispatch to the given handler when the pattern matches and the HTTP method is PATCH. See the documentation for type Mux for a description of what types are accepted for pattern and handler.

func (*Mux) Post

func (rt *Mux) Post(pattern interface{}, handler interface{})

Dispatch to the given handler when the pattern matches and the HTTP method is POST. See the documentation for type Mux for a description of what types are accepted for pattern and handler.

func (*Mux) Put

func (rt *Mux) Put(pattern interface{}, handler interface{})

Dispatch to the given handler when the pattern matches and the HTTP method is PUT. See the documentation for type Mux for a description of what types are accepted for pattern and handler.

func (*Mux) ServeHTTP

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

func (*Mux) ServeHTTPC

func (m *Mux) ServeHTTPC(c C, w http.ResponseWriter, r *http.Request)

ServeHTTPC creates a context dependent request with the given Mux. Satisfies the web.Handler interface.

func (*Mux) Trace

func (rt *Mux) Trace(pattern interface{}, handler interface{})

Dispatch to the given handler when the pattern matches and the HTTP method is TRACE. See the documentation for type Mux for a description of what types are accepted for pattern and handler.

func (*Mux) Use

func (m *Mux) Use(middleware interface{})

Append the given middleware to the middleware stack. See the documentation for type Mux for a list of valid middleware types.

No attempt is made to enforce the uniqueness of middlewares. It is illegal to call this function concurrently with active requests.

type Pattern

type Pattern interface {
	// In practice, most real-world routes have a string prefix that can be
	// used to quickly determine if a pattern is an eligible match. The
	// router uses the result of this function to optimize away calls to the
	// full Match function, which is likely much more expensive to compute.
	// If your Pattern does not support prefixes, this function should
	// return the empty string.
	Prefix() string
	// Returns true if the request satisfies the pattern. This function is
	// free to examine both the request and the context to make this
	// decision. Match should not modify either argument, and since it will
	// potentially be called several times over the course of matching a
	// request, it should be reasonably efficient.
	Match(r *http.Request, c *C) bool
	// Run the pattern on the request and context, modifying the context as
	// necessary to bind URL parameters or other parsed state.
	Run(r *http.Request, c *C)
}

A Pattern determines whether or not a given request matches some criteria. They are often used in routes, which are essentially (pattern, methodSet, handler) tuples. If the method and pattern match, the given handler is used.

Built-in implementations of this interface are used to implement regular expression and string matching.

Directories

Path Synopsis
Package middleware provides several standard middleware implementations.
Package middleware provides several standard middleware implementations.
Package util contains various functions that are helpful when writing http middleware.
Package util contains various functions that are helpful when writing http middleware.

Jump to

Keyboard shortcuts

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