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
- type C
- type Handler
- type HandlerFunc
- type Mux
- func (m *Mux) Abandon(middleware interface{}) error
- func (m *Mux) Compile()
- func (m *Mux) Connect(pattern interface{}, handler interface{})
- func (m *Mux) Delete(pattern interface{}, handler interface{})
- func (m *Mux) Get(pattern interface{}, handler interface{})
- func (m *Mux) Handle(pattern interface{}, handler interface{})
- func (m *Mux) Head(pattern interface{}, handler interface{})
- func (m *Mux) Insert(middleware, before interface{}) error
- func (m *Mux) NotFound(handler interface{})
- func (m *Mux) Options(pattern interface{}, handler interface{})
- func (m *Mux) Patch(pattern interface{}, handler interface{})
- func (m *Mux) Post(pattern interface{}, handler interface{})
- func (m *Mux) Put(pattern interface{}, handler interface{})
- func (m *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (m *Mux) ServeHTTPC(c C, w http.ResponseWriter, r *http.Request)
- func (m *Mux) Trace(pattern interface{}, handler interface{})
- func (m *Mux) Use(middleware interface{})
- type Pattern
Constants ¶
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 ¶
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 "/*" 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 name "*" 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. 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 (*Mux) Abandon ¶
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 ¶
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 ¶
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.
Source Files ¶
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. |