@ -1,26 +1,18 @@
/ *
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 .
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 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 .
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 :
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 )
@ -28,7 +20,7 @@ Use your favorite HTTP verbs:
w . Write ( [ ] byte ( "Hello world!" ) )
} )
Bind parameters using either Sinatra - like pattern s or regular expressions :
Bind parameters using either named capture s 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" ] )
@ -41,33 +33,32 @@ Bind parameters using either Sinatra-like patterns or regular expressions:
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 :
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 :
m . Use ( func ( h http . Handler ) http . 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 )
} )
m . Use ( func ( c * web . C , h http . Handler ) http . Handler {
}
func AuthMiddleware ( 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 { } )
}
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 ) )
@ -83,46 +74,41 @@ import (
)
/ *
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 .
C is a request - local context object which is threaded through all compliant
middleware layers and given to the final request handler .
* /
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 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
// 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 { }
// 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 { }
}
// 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.
// Handler is similar to net/http's http.Handler, but also accepts a Goji
// context object.
type Handler interface {
http . Handler
ServeHTTPC ( 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 .
// HandlerFunc is similar to net/http's http.HandlerFunc, but supports a context
// object. Implements both http.Handler and web.Handler.
type HandlerFunc func ( C , http . ResponseWriter , * 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 ( h HandlerFunc ) ServeHTTP ( w http . ResponseWriter , r * http . Request ) {
h ( C { } , w , r )
}
// ServeHTTPC wraps ServeHTTP with a context paramet er.
// ServeHTTPC implements Handl er.
func ( h HandlerFunc ) ServeHTTPC ( c C , w http . ResponseWriter , r * http . Request ) {
h ( c , w , r )
}