1 package goji 2 3 import ( 4 "context" 5 "net/http" 6 7 "goji.io/internal" 8 ) 9 10 /* 11 Mux is a HTTP multiplexer / router similar to net/http.ServeMux. 12 13 Muxes multiplex traffic between many http.Handlers by selecting the first 14 applicable Pattern. They then call a common middleware stack, finally passing 15 control to the selected http.Handler. See the documentation on the Handle 16 function for more information about how routing is performed, the documentation 17 on the Pattern type for more information about request matching, and the 18 documentation for the Use method for more about middleware. 19 20 Muxes cannot be configured concurrently from multiple goroutines, nor can they 21 be configured concurrently with requests. 22 */ 23 type Mux struct { 24 handler http.Handler 25 middleware []func(http.Handler) http.Handler 26 router router 27 root bool 28 } 29 30 /* 31 NewMux returns a new Mux with no configured middleware or routes. 32 */ 33 func NewMux() *Mux { 34 m := SubMux() 35 m.root = true 36 return m 37 } 38 39 /* 40 SubMux returns a new Mux with no configured middleware or routes, and which 41 inherits routing information from the passed context. This is especially useful 42 when using one Mux as a http.Handler registered to another "parent" Mux. 43 44 For example, a common pattern is to organize applications in a way that mirrors 45 the structure of its URLs: a photo-sharing site might have URLs that start with 46 "/users/" and URLs that start with "/albums/", and might be organized using 47 three Muxes: 48 49 root := NewMux() 50 users := SubMux() 51 root.Handle(pat.New("/users/*"), users) 52 albums := SubMux() 53 root.Handle(pat.New("/albums/*"), albums) 54 55 // e.g., GET /users/carl 56 users.Handle(pat.Get("/:name"), renderProfile) 57 // e.g., POST /albums/ 58 albums.Handle(pat.Post("/"), newAlbum) 59 */ 60 func SubMux() *Mux { 61 m := &Mux{} 62 m.buildChain() 63 return m 64 } 65 66 // ServeHTTP implements net/http.Handler. 67 func (m *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) { 68 if m.root { 69 ctx := r.Context() 70 ctx = context.WithValue(ctx, internal.Path, r.URL.EscapedPath()) 71 r = r.WithContext(ctx) 72 } 73 r = m.router.route(r) 74 m.handler.ServeHTTP(w, r) 75 } 76 77 var _ http.Handler = &Mux{} 78