Skip to content

Commit

Permalink
feat(middleware): add match wrappers
Browse files Browse the repository at this point in the history
  • Loading branch information
tdakkota committed Sep 29, 2022
1 parent 411bbd2 commit f303f76
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 7 deletions.
79 changes: 79 additions & 0 deletions middleware/match.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package middleware

import (
"regexp"

"github.com/ogen-go/ogen/internal/xmaps"
)

// OperationID calls the next middleware if request operation ID matches the given operationID.
func OperationID(m Middleware, operationID ...string) Middleware {
switch len(operationID) {
case 0:
return justCallNext
case 1:
val := operationID[0]
return func(req Request, next Next) (Response, error) {
if req.OperationID == val {
return m(req, next)
}
return next(req)
}
default:
set := xmaps.BuildSet(operationID...)
return func(req Request, next Next) (Response, error) {
if _, ok := set[req.OperationID]; ok {
return m(req, next)
}
return next(req)
}
}
}

// OperationName calls the next middleware if request operation name matches the given operationName.
func OperationName(m Middleware, operationName ...string) Middleware {
switch len(operationName) {
case 0:
return justCallNext
case 1:
val := operationName[0]
return func(req Request, next Next) (Response, error) {
if req.OperationName == val {
return m(req, next)
}
return next(req)
}
default:
set := xmaps.BuildSet(operationName...)
return func(req Request, next Next) (Response, error) {
if _, ok := set[req.OperationName]; ok {
return m(req, next)
}
return next(req)
}
}
}

// PathRegex calls the next middleware if request path matches the given regex.
func PathRegex(re *regexp.Regexp, m Middleware) Middleware {
if re == nil {
return justCallNext
}

return func(req Request, next Next) (Response, error) {
if re.MatchString(req.Raw.URL.Path) {
return m(req, next)
}
return next(req)
}
}

// BodyType calls the next middleware if request body type matches the given type.
func BodyType[T any](m Middleware) Middleware {
return func(req Request, next Next) (Response, error) {
if _, ok := req.Body.(T); ok {
return m(req, next)
}
return next(req)
}
}
8 changes: 5 additions & 3 deletions middleware/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@ type (
Middleware func(req Request, next Next) (Response, error)
)

func justCallNext(req Request, next Next) (Response, error) {
return next(req)
}

// ChainMiddlewares chains middlewares into a single middleware, which will be executed in the order they are passed.
func ChainMiddlewares(m ...Middleware) Middleware {
if len(m) == 0 {
return func(req Request, next Next) (Response, error) {
return next(req)
}
return justCallNext
}
tail := ChainMiddlewares(m[1:]...)
return func(req Request, next Next) (Response, error) {
Expand Down
5 changes: 1 addition & 4 deletions middleware/middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,11 @@ func TestChainMiddlewares(t *testing.T) {

func BenchmarkChainMiddlewares(b *testing.B) {
const N = 20
noop := func(req Request, next Next) (Response, error) {
return next(req)
}

var (
chain = ChainMiddlewares(func() (r []Middleware) {
for i := 0; i < N; i++ {
r = append(r, noop)
r = append(r, justCallNext)
}
return r
}()...)
Expand Down

0 comments on commit f303f76

Please sign in to comment.