aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/zenazn/goji/web/mux.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/zenazn/goji/web/mux.go')
-rw-r--r--vendor/github.com/zenazn/goji/web/mux.go213
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()
+}