Skip to content

Commit

Permalink
Merge pull request #27 from guregu/multiware-wildcard
Browse files Browse the repository at this point in the history
Allow registration of multiple wildcard middlewares
  • Loading branch information
guregu authored Sep 8, 2016
2 parents d3fd276 + b4b2400 commit b4588ae
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 57 deletions.
41 changes: 27 additions & 14 deletions kami_17_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,51 +59,64 @@ func TestKami(t *testing.T) {
ctx = expect(ctx, 5)
return ctx
})
kami.Use("/a/*files", func(ctx context.Context, w http.ResponseWriter, r *http.Request) context.Context {
expectEqual(ctx, r.Context(), 6)
ctx = expect(ctx, 6)
return ctx
})
kami.Get("/a/b", func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
expectEqual(ctx, r.Context(), 5)
if prev := ctx.Value(5).(int); prev != 5 {
t.Error("handler: missing", 5)
expectEqual(ctx, r.Context(), 6)
if prev := ctx.Value(6).(int); prev != 6 {
t.Error("handler: missing", 6)
}
*(ctx.Value("handler").(*bool)) = true

w.WriteHeader(http.StatusTeapot)
})
kami.After("/a/*files", func(ctx context.Context, w http.ResponseWriter, r *http.Request) context.Context {
expectEqual(ctx, r.Context(), 6)
ctx = expect(ctx, 6)
expectEqual(ctx, r.Context(), 8)
ctx = expect(ctx, 8)
if !*(ctx.Value("handler").(*bool)) {
t.Error("ran before handler")
}
return ctx
})
kami.After("/a/b", kami.Afterware(func(ctx context.Context, w mutil.WriterProxy, r *http.Request) context.Context {
kami.After("/a/*files", func(ctx context.Context, w http.ResponseWriter, r *http.Request) context.Context {
expectEqual(ctx, r.Context(), 7)
ctx = expect(ctx, 7)
if !*(ctx.Value("handler").(*bool)) {
t.Error("ran before handler")
}
return ctx
}))
kami.After("/a/", func(ctx context.Context, w mutil.WriterProxy, r *http.Request) context.Context {
})
kami.After("/a/b", kami.Afterware(func(ctx context.Context, w mutil.WriterProxy, r *http.Request) context.Context {
expectEqual(ctx, r.Context(), 9)
ctx = expect(ctx, 9)
return ctx
}))
kami.After("/a/", func(ctx context.Context, w mutil.WriterProxy, r *http.Request) context.Context {
expectEqual(ctx, r.Context(), 11)
ctx = expect(ctx, 11)
return ctx
})
kami.After("/a/", func(ctx context.Context, w mutil.WriterProxy, r *http.Request) context.Context {
expectEqual(ctx, r.Context(), 8)
ctx = expect(ctx, 8)
expectEqual(ctx, r.Context(), 10)
ctx = expect(ctx, 10)
return ctx
})
kami.After("/", func(ctx context.Context, w mutil.WriterProxy, r *http.Request) context.Context {
expectEqual(ctx, r.Context(), 10)
expectEqual(ctx, r.Context(), 12)
if status := w.Status(); status != http.StatusTeapot {
t.Error("wrong status", status)
}

ctx = expect(ctx, 10)
ctx = expect(ctx, 12)
*(ctx.Value("done").(*bool)) = true
panic("🍣")
return nil
})
kami.PanicHandler = func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
expectEqual(ctx, r.Context(), 11)
expectEqual(ctx, r.Context(), 13)
if got := kami.Exception(ctx); got.(string) != "🍣" {
t.Error("panic handler: expected sushi, got", got)
}
Expand All @@ -113,7 +126,7 @@ func TestKami(t *testing.T) {
*(ctx.Value("recovered").(*bool)) = true
}
kami.LogHandler = func(ctx context.Context, w mutil.WriterProxy, r *http.Request) {
expectEqual(ctx, r.Context(), 12)
expectEqual(ctx, r.Context(), 14)
if !*(ctx.Value("recovered").(*bool)) {
t.Error("didn't recover")
}
Expand Down
29 changes: 20 additions & 9 deletions kami_old_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,39 +49,50 @@ func TestKami(t *testing.T) {
ctx = expect(ctx, 5)
return ctx
})
kami.Use("/a/*files", func(ctx context.Context, w http.ResponseWriter, r *http.Request) context.Context {
ctx = expect(ctx, 6)
return ctx
})
kami.Get("/a/b", func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
if prev := ctx.Value(5).(int); prev != 5 {
t.Error("handler: missing", 5)
if prev := ctx.Value(6).(int); prev != 6 {
t.Error("handler: missing", 6)
}
*(ctx.Value("handler").(*bool)) = true

w.WriteHeader(http.StatusTeapot)
})
kami.After("/a/*files", func(ctx context.Context, w http.ResponseWriter, r *http.Request) context.Context {
ctx = expect(ctx, 6)
ctx = expect(ctx, 8)
if !*(ctx.Value("handler").(*bool)) {
t.Error("ran before handler")
}
return ctx
})
kami.After("/a/b", kami.Afterware(func(ctx context.Context, w mutil.WriterProxy, r *http.Request) context.Context {
kami.After("/a/*files", func(ctx context.Context, w http.ResponseWriter, r *http.Request) context.Context {
ctx = expect(ctx, 7)
if !*(ctx.Value("handler").(*bool)) {
t.Error("ran before handler")
}
return ctx
}))
kami.After("/a/", func(ctx context.Context) context.Context {
})
kami.After("/a/b", kami.Afterware(func(ctx context.Context, w mutil.WriterProxy, r *http.Request) context.Context {
ctx = expect(ctx, 9)
return ctx
}))
kami.After("/a/", func(ctx context.Context, w mutil.WriterProxy, r *http.Request) context.Context {
ctx = expect(ctx, 11)
return ctx
})
kami.After("/a/", func(ctx context.Context) context.Context {
ctx = expect(ctx, 8)
kami.After("/a/", func(ctx context.Context, w mutil.WriterProxy, r *http.Request) context.Context {
ctx = expect(ctx, 10)
return ctx
})
kami.After("/", func(ctx context.Context, w mutil.WriterProxy, r *http.Request) context.Context {
if status := w.Status(); status != http.StatusTeapot {
t.Error("wrong status", status)
}

ctx = expect(ctx, 10)
ctx = expect(ctx, 12)
*(ctx.Value("done").(*bool)) = true
panic("🍣")
return nil
Expand Down
17 changes: 15 additions & 2 deletions middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,14 @@ func (m *wares) Use(path string, mw MiddlewareType) {
if m.wildcards == nil {
m.wildcards = treemux.New()
}
m.wildcards.Set(path, convert(mw))
mw := convert(mw)
iface, _ := m.wildcards.Get(path)
if chain, ok := iface.(*[]Middleware); ok {
*chain = append(*chain, mw)
} else {
chain := []Middleware{mw}
m.wildcards.Set(path, &chain)
}
} else {
if m.middleware == nil {
m.middleware = make(map[string][]Middleware)
Expand All @@ -44,7 +51,13 @@ func (m *wares) After(path string, afterware AfterwareType) {
if m.afterWildcards == nil {
m.afterWildcards = treemux.New()
}
m.afterWildcards.Set(path, aw)
iface, _ := m.afterWildcards.Get(path)
if chain, ok := iface.(*[]Afterware); ok {
*chain = append([]Afterware{aw}, *chain...)
} else {
chain := []Afterware{aw}
m.afterWildcards.Set(path, &chain)
}
} else {
if m.afterware == nil {
m.afterware = make(map[string][]Afterware)
Expand Down
42 changes: 23 additions & 19 deletions middleware_17.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ type Middleware func(context.Context, http.ResponseWriter, *http.Request) contex
// kami will try its best to convert standard, non-context middleware.
// See the Use function for important information about how kami middleware is run.
// The following concrete types are accepted:
// - Middleware
// - func(context.Context, http.ResponseWriter, *http.Request) context.Context
// - func(http.ResponseWriter, *http.Request) context.Context
// - func(http.Handler) http.Handler [* see Use docs]
// - func(http.ContextHandler) http.ContextHandler [* see Use docs]
// - Middleware
// - func(context.Context, http.ResponseWriter, *http.Request) context.Context
// - func(http.ResponseWriter, *http.Request) context.Context
// - func(http.Handler) http.Handler [* see Use docs]
// - func(http.ContextHandler) http.ContextHandler [* see Use docs]
// - http.Handler [read only]
// - func(http.ResponseWriter, *http.Request) [read only]
// The old x/net/context is also supported.
Expand Down Expand Up @@ -76,17 +76,19 @@ func (m *wares) run(ctx context.Context, w http.ResponseWriter, r *http.Request)
if m.wildcards != nil {
// wildcard middleware
if wild, params := m.wildcards.Get(r.URL.Path); wild != nil {
if mw, ok := wild.(Middleware); ok {
if mws, ok := wild.(*[]Middleware); ok {
ctx = mergeParams(ctx, params)
r = r.WithContext(ctx)
result := mw(ctx, w, r)
if result == nil {
return r, ctx, false
}
if result != ctx {
r = r.WithContext(result)
for _, mw := range *mws {
result := mw(ctx, w, r)
if result == nil {
return r, ctx, false
}
if result != ctx {
r = r.WithContext(result)
}
ctx = result
}
ctx = result
}
}
}
Expand All @@ -100,15 +102,17 @@ func (m *wares) after(ctx context.Context, w mutil.WriterProxy, r *http.Request)
if m.afterWildcards != nil {
// wildcard afterware
if wild, params := m.afterWildcards.Get(r.URL.Path); wild != nil {
if aw, ok := wild.(Afterware); ok {
if aws, ok := wild.(*[]Afterware); ok {
ctx = mergeParams(ctx, params)
r = r.WithContext(ctx)
result := aw(ctx, w, r)
if result != nil {
if result != ctx {
r = r.WithContext(result)
for _, aw := range *aws {
result := aw(ctx, w, r)
if result != nil {
if result != ctx {
r = r.WithContext(result)
}
ctx = result
}
ctx = result
}
}
}
Expand Down
30 changes: 17 additions & 13 deletions middleware_old.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ type Middleware func(context.Context, http.ResponseWriter, *http.Request) contex
// kami will try its best to convert standard, non-context middleware.
// See the Use function for important information about how kami middleware is run.
// The following concrete types are accepted:
// - Middleware
// - func(context.Context, http.ResponseWriter, *http.Request) context.Context
// - func(http.Handler) http.Handler [* see Use docs]
// - func(http.ContextHandler) http.ContextHandler [* see Use docs]
// - Middleware
// - func(context.Context, http.ResponseWriter, *http.Request) context.Context
// - func(http.Handler) http.Handler [* see Use docs]
// - func(http.ContextHandler) http.ContextHandler [* see Use docs]
type MiddlewareType interface{}

// Afterware is a function that will run after middleware and the request.
Expand Down Expand Up @@ -67,13 +67,15 @@ func (m *wares) run(ctx context.Context, w http.ResponseWriter, r *http.Request)
if m.wildcards != nil {
// wildcard middleware
if wild, params := m.wildcards.Get(r.URL.Path); wild != nil {
if mw, ok := wild.(Middleware); ok {
if mws, ok := wild.(*[]Middleware); ok {
ctx = mergeParams(ctx, params)
result := mw(ctx, w, r)
if result == nil {
return ctx, false
for _, mw := range *mws {
result := mw(ctx, w, r)
if result == nil {
return ctx, false
}
ctx = result
}
ctx = result
}
}
}
Expand All @@ -87,11 +89,13 @@ func (m *wares) after(ctx context.Context, w mutil.WriterProxy, r *http.Request)
if m.afterWildcards != nil {
// wildcard afterware
if wild, params := m.afterWildcards.Get(r.URL.Path); wild != nil {
if aw, ok := wild.(Afterware); ok {
if aws, ok := wild.(*[]Afterware); ok {
ctx = mergeParams(ctx, params)
result := aw(ctx, w, r)
if result != nil {
ctx = result
for _, aw := range *aws {
result := aw(ctx, w, r)
if result != nil {
ctx = result
}
}
}
}
Expand Down

0 comments on commit b4588ae

Please sign in to comment.