diff options
| author | Felix Hanley <felix@userspace.com.au> | 2016-12-05 08:16:58 +0000 |
|---|---|---|
| committer | Felix Hanley <felix@userspace.com.au> | 2016-12-05 08:16:58 +0000 |
| commit | b049991a46a2f619344bd6e915745703864d0134 (patch) | |
| tree | ec1d3897a7b69c7c63a3774d4c42dfbb8cb46432 /vendor/github.com/zenazn/goji/web/mux.go | |
| parent | e1c3d6f7db06d592538f1162b2b6b9f1b6efa330 (diff) | |
| download | go-dict2rest-b049991a46a2f619344bd6e915745703864d0134.tar.gz go-dict2rest-b049991a46a2f619344bd6e915745703864d0134.tar.bz2 | |
Diffstat (limited to 'vendor/github.com/zenazn/goji/web/mux.go')
| -rw-r--r-- | vendor/github.com/zenazn/goji/web/mux.go | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/vendor/github.com/zenazn/goji/web/mux.go b/vendor/github.com/zenazn/goji/web/mux.go new file mode 100644 index 0000000..18b9991 --- /dev/null +++ b/vendor/github.com/zenazn/goji/web/mux.go @@ -0,0 +1,213 @@ +package web + +import ( + "net/http" +) + +/* +Mux is an HTTP multiplexer, much like net/http's ServeMux. It functions as both +a middleware stack and as an HTTP router. + +Middleware provide a great abstraction for actions that must be performed on +every request, such as request logging and authentication. To append, insert, +and remove middleware, you can call the Use, Insert, and Abandon functions +respectively. + +Routes may be added using any of the HTTP verb functions (Get, Post, etc.), or +through the generic Handle function. Goji's routing algorithm is very simple: +routes are processed in the order they are added, and the first matching route +will be executed. Routes match if their HTTP method and Pattern both match. +*/ +type Mux struct { + ms mStack + rt router +} + +// New creates a new Mux without any routes or middleware. +func New() *Mux { + mux := Mux{ + ms: mStack{ + stack: make([]mLayer, 0), + pool: makeCPool(), + }, + rt: router{ + routes: make([]route, 0), + notFound: parseHandler(http.NotFound), + }, + } + mux.ms.router = &mux.rt + return &mux +} + +// ServeHTTP processes HTTP requests. Satisfies net/http.Handler. +func (m *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) { + stack := m.ms.alloc() + stack.ServeHTTP(w, r) + m.ms.release(stack) +} + +// ServeHTTPC creates a context dependent request with the given Mux. Satisfies +// the Handler interface. +func (m *Mux) ServeHTTPC(c C, w http.ResponseWriter, r *http.Request) { + stack := m.ms.alloc() + stack.ServeHTTPC(c, w, r) + m.ms.release(stack) +} + +// Middleware Stack functions + +// Use appends the given middleware to the middleware stack. +// +// No attempt is made to enforce the uniqueness of middlewares. It is illegal to +// call this function concurrently with active requests. +func (m *Mux) Use(middleware MiddlewareType) { + m.ms.Use(middleware) +} + +// Insert inserts the given middleware immediately before a given existing +// middleware in the stack. Returns an error if "before" cannot be found in the +// current stack. +// +// 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 (m *Mux) Insert(middleware, before MiddlewareType) error { + return m.ms.Insert(middleware, before) +} + +// Abandon removes 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 (m *Mux) Abandon(middleware MiddlewareType) error { + return m.ms.Abandon(middleware) +} + +// Router functions + +type routerMiddleware struct { + m *Mux + c *C + h http.Handler +} + +func (rm routerMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if rm.c.Env == nil { + rm.c.Env = make(map[interface{}]interface{}, 1) + } + rm.c.Env[MatchKey] = rm.m.rt.getMatch(rm.c, w, r) + rm.h.ServeHTTP(w, r) +} + +/* +Router is a middleware that performs routing and stores the resulting Match in +Goji's environment. If a routing Match is present at the end of the middleware +stack, that Match is used instead of re-routing. + +This middleware is especially useful to create post-routing middleware, e.g. a +request logger which prints which pattern or handler was selected, or an +authentication middleware which only applies to certain routes. + +If you use nested Muxes with explicit routing, you should be aware that the +explicit routing information set by an outer Mux can be picked up by an inner +Mux, inadvertently causing an infinite routing loop. If you use both explicit +routing and nested Muxes, you should be sure to unset MatchKey before the inner +Mux performs routing (or attach a Router to the inner Mux as well). +*/ +func (m *Mux) Router(c *C, h http.Handler) http.Handler { + return routerMiddleware{m, c, h} +} + +/* +Handle dispatches to the given handler when the pattern matches, regardless of +HTTP method. + +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 (m *Mux) Handle(pattern PatternType, handler HandlerType) { + m.rt.handleUntyped(pattern, mALL, handler) +} + +// Connect dispatches to the given handler when the pattern matches and the HTTP +// method is CONNECT. +func (m *Mux) Connect(pattern PatternType, handler HandlerType) { + m.rt.handleUntyped(pattern, mCONNECT, handler) +} + +// Delete dispatches to the given handler when the pattern matches and the HTTP +// method is DELETE. +func (m *Mux) Delete(pattern PatternType, handler HandlerType) { + m.rt.handleUntyped(pattern, mDELETE, handler) +} + +// Get dispatches to the given handler when the pattern matches and the HTTP +// method is GET. +// +// 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 (m *Mux) Get(pattern PatternType, handler HandlerType) { + m.rt.handleUntyped(pattern, mGET|mHEAD, handler) +} + +// Head dispatches to the given handler when the pattern matches and the HTTP +// method is HEAD. +func (m *Mux) Head(pattern PatternType, handler HandlerType) { + m.rt.handleUntyped(pattern, mHEAD, handler) +} + +// Options dispatches to the given handler when the pattern matches and the HTTP +// method is OPTIONS. +func (m *Mux) Options(pattern PatternType, handler HandlerType) { + m.rt.handleUntyped(pattern, mOPTIONS, handler) +} + +// Patch dispatches to the given handler when the pattern matches and the HTTP +// method is PATCH. +func (m *Mux) Patch(pattern PatternType, handler HandlerType) { + m.rt.handleUntyped(pattern, mPATCH, handler) +} + +// Post dispatches to the given handler when the pattern matches and the HTTP +// method is POST. +func (m *Mux) Post(pattern PatternType, handler HandlerType) { + m.rt.handleUntyped(pattern, mPOST, handler) +} + +// Put dispatches to the given handler when the pattern matches and the HTTP +// method is PUT. +func (m *Mux) Put(pattern PatternType, handler HandlerType) { + m.rt.handleUntyped(pattern, mPUT, handler) +} + +// Trace dispatches to the given handler when the pattern matches and the HTTP +// method is TRACE. +func (m *Mux) Trace(pattern PatternType, handler HandlerType) { + m.rt.handleUntyped(pattern, mTRACE, handler) +} + +// NotFound sets the fallback (i.e., 404) handler for this mux. +// +// 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 (m *Mux) NotFound(handler HandlerType) { + m.rt.notFound = parseHandler(handler) +} + +// Compile compiles 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 (m *Mux) Compile() { + m.rt.compile() +} |
