web

package
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: Jan 31, 2015 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

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

This package attempts to solve three problems that net/http does not. First, it allows you to specify flexible patterns, including routes with named parameters and regular expressions. 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 and the interfaces you know and love from net/http:

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 named captures 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 the intervening middleware or handlers support contexts. Middleware are encouraged to use the Env parameter to pass request-scoped data to other middleware and to the final handler:

func LoggerMiddleware(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)
}
func AuthMiddleware(c *web.C, h http.Handler) http.Handler {
	handler := func(w http.ResponseWriter, r *http.Request) {
		if cookie, err := r.Cookie("user"); err == nil {
			c.Env["user"] = cookie.Value
		}
		h.ServeHTTP(w, r)
	}
	return http.HandlerFunc(handler)
}

// This makes the AuthMiddleware above a little cleaner
m.Use(middleware.EnvInit)
m.Use(AuthMiddleware)
m.Use(LoggerMiddleware)
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 {
	// URLParams is a map of variables extracted from the URL (typically
	// from the path portion) during routing. See the documentation for the
	// URL Pattern you are using (or the documentation for ParsePattern for
	// the case of standard pattern types) for more information about how
	// variables are extracted and named.
	URLParams map[string]string
	// Env is a free-form environment for storing request-local data. Keys
	// may be arbitrary types that support equality, however package-private
	// types with type-safe accessors provide a convenient way for packages
	// to mediate access to their request-local data.
	Env map[interface{}]interface{}
}

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

type Handler

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

Handler is similar to net/http's http.Handler, but also accepts a Goji context object.

type HandlerFunc

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

HandlerFunc is similar to net/http's http.HandlerFunc, but supports a context object. Implements both http.Handler and web.Handler.

func (HandlerFunc) ServeHTTP

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

ServeHTTP implements http.Handler, allowing HandlerFunc's to be used with net/http and other compliant routers. When used in this way, the underlying function will be passed an empty context.

func (HandlerFunc) ServeHTTPC

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

ServeHTTPC implements Handler.

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 will be passed to ParsePattern, which takes a web.Pattern, a string, or a regular expression (more information can be found in the ParsePattern documentation). 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 (m *Mux) Compile()

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 (m *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 (m *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 (m *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 (m *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 (m *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 (m *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 (m *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 (m *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 (m *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 (m *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)

ServeHTTP processes HTTP requests. It make Muxes satisfy net/http.Handler.

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 (m *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.

func ParsePattern added in v0.8.2

func ParsePattern(raw interface{}) Pattern

ParsePattern is used internally by Goji to parse route patterns. It is exposed publicly to make it easier to write thin wrappers around the built-in Pattern implementations.

Although its parameter has type interface{}, ParsePattern only accepts arguments of three types:

  • web.Pattern, which is passed through
  • string, which is interpreted as a Sinatra-like URL 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 "/*" will match any route with that prefix. For instance, the pattern "/u/:name/*" will match "/u/carl/" and "/u/carl/projects/123", but not "/u/carl" (because there is no trailing slash). In addition to any names bound in the pattern, the special key "*" is bound to the unmatched tail of the match, but including the leading "/". So for the two matching examples above, "*" would be bound to "/" and "/projects/123" respectively.
  • regexp.Regexp, which is assumed to be a Perl-style regular expression that is anchored on the left (i.e., the beginning of the string). If your regular expression is not anchored on the left, a hopefully-identical left-anchored regular expression will be created and used instead. Named capturing groups will bind URLParams of the same name; unnamed capturing groups will be bound to the variables "$1", "$2", etc.

ParsePattern fatally exits (using log.Fatalf) if it is passed a value of an unexpected type. It is the caller's responsibility to ensure that ParsePattern is called in a type-safe manner.

Directories

Path Synopsis
Package middleware provides several standard middleware implementations.
Package middleware provides several standard middleware implementations.
Package mutil contains various functions that are helpful when writing http middleware.
Package mutil 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