Skip to content

Commit 6d381a5

Browse files
committed
feat: add context management to framework handlers and update related tests
1 parent 9b38629 commit 6d381a5

8 files changed

Lines changed: 71 additions & 22 deletions

File tree

ROADMAP.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
## Features
44

5-
- [ ] Shared context
65
- [ ] Response Headers
76
- [ ] Non-json responses
87
- [ ] Middleware

pkg/context/context.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,7 @@ func (c *Context) Contains(key string) bool {
2222
_, ok := c.data[key]
2323
return ok
2424
}
25+
26+
func (c *Context) Delete(key string) {
27+
delete(c.data, key)
28+
}

pkg/framework/fiberframework/framework.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"net/http"
55
"net/http/httptest"
66

7+
"github.com/go-simpl/simplapi/pkg/context"
78
"github.com/go-simpl/simplapi/pkg/framework"
89
"github.com/gofiber/fiber/v2"
910
"github.com/gofiber/fiber/v2/middleware/adaptor"
@@ -21,49 +22,49 @@ func New(app *fiber.App) framework.Framework {
2122

2223
func (f *fiberFramework) GET(path string, handler framework.FrameworkHandler) {
2324
f.app.Get(path, func(c *fiber.Ctx) error {
24-
return handler(NewRequest(c), NewResponse(c))
25+
return handler(NewRequest(c), NewResponse(c), context.New())
2526
})
2627
}
2728

2829
func (f *fiberFramework) POST(path string, handler framework.FrameworkHandler) {
2930
f.app.Post(path, func(c *fiber.Ctx) error {
30-
return handler(NewRequest(c), NewResponse(c))
31+
return handler(NewRequest(c), NewResponse(c), context.New())
3132
})
3233
}
3334

3435
func (f *fiberFramework) PUT(path string, handler framework.FrameworkHandler) {
3536
f.app.Put(path, func(c *fiber.Ctx) error {
36-
return handler(NewRequest(c), NewResponse(c))
37+
return handler(NewRequest(c), NewResponse(c), context.New())
3738
})
3839
}
3940

4041
func (f *fiberFramework) PATCH(path string, handler framework.FrameworkHandler) {
4142
f.app.Patch(path, func(c *fiber.Ctx) error {
42-
return handler(NewRequest(c), NewResponse(c))
43+
return handler(NewRequest(c), NewResponse(c), context.New())
4344
})
4445
}
4546

4647
func (f *fiberFramework) DELETE(path string, handler framework.FrameworkHandler) {
4748
f.app.Delete(path, func(c *fiber.Ctx) error {
48-
return handler(NewRequest(c), NewResponse(c))
49+
return handler(NewRequest(c), NewResponse(c), context.New())
4950
})
5051
}
5152

5253
func (f *fiberFramework) OPTIONS(path string, handler framework.FrameworkHandler) {
5354
f.app.Options(path, func(c *fiber.Ctx) error {
54-
return handler(NewRequest(c), NewResponse(c))
55+
return handler(NewRequest(c), NewResponse(c), context.New())
5556
})
5657
}
5758

5859
func (f *fiberFramework) HEAD(path string, handler framework.FrameworkHandler) {
5960
f.app.Head(path, func(c *fiber.Ctx) error {
60-
return handler(NewRequest(c), NewResponse(c))
61+
return handler(NewRequest(c), NewResponse(c), context.New())
6162
})
6263
}
6364

6465
func (f *fiberFramework) TRACE(path string, handler framework.FrameworkHandler) {
6566
f.app.Trace(path, func(c *fiber.Ctx) error {
66-
return handler(NewRequest(c), NewResponse(c))
67+
return handler(NewRequest(c), NewResponse(c), context.New())
6768
})
6869
}
6970

pkg/framework/ginframework/framework.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"net/http/httptest"
66

77
"github.com/gin-gonic/gin"
8+
"github.com/go-simpl/simplapi/pkg/context"
89
"github.com/go-simpl/simplapi/pkg/framework"
910
)
1011

@@ -20,7 +21,7 @@ func New(engine *gin.Engine) framework.Framework {
2021

2122
func (g *ginFramework) GET(path string, handler framework.FrameworkHandler) {
2223
g.engine.GET(path, func(c *gin.Context) {
23-
err := handler(NewRequest(c), NewResponse(c))
24+
err := handler(NewRequest(c), NewResponse(c), context.New())
2425
if err != nil {
2526
c.AbortWithError(http.StatusInternalServerError, err)
2627
}
@@ -29,7 +30,7 @@ func (g *ginFramework) GET(path string, handler framework.FrameworkHandler) {
2930

3031
func (g *ginFramework) POST(path string, handler framework.FrameworkHandler) {
3132
g.engine.POST(path, func(c *gin.Context) {
32-
err := handler(NewRequest(c), NewResponse(c))
33+
err := handler(NewRequest(c), NewResponse(c), context.New())
3334
if err != nil {
3435
c.AbortWithError(http.StatusInternalServerError, err)
3536
}
@@ -38,7 +39,7 @@ func (g *ginFramework) POST(path string, handler framework.FrameworkHandler) {
3839

3940
func (g *ginFramework) PUT(path string, handler framework.FrameworkHandler) {
4041
g.engine.PUT(path, func(c *gin.Context) {
41-
err := handler(NewRequest(c), NewResponse(c))
42+
err := handler(NewRequest(c), NewResponse(c), context.New())
4243
if err != nil {
4344
c.AbortWithError(http.StatusInternalServerError, err)
4445
}
@@ -47,7 +48,7 @@ func (g *ginFramework) PUT(path string, handler framework.FrameworkHandler) {
4748

4849
func (g *ginFramework) PATCH(path string, handler framework.FrameworkHandler) {
4950
g.engine.PATCH(path, func(c *gin.Context) {
50-
err := handler(NewRequest(c), NewResponse(c))
51+
err := handler(NewRequest(c), NewResponse(c), context.New())
5152
if err != nil {
5253
c.AbortWithError(http.StatusInternalServerError, err)
5354
}
@@ -56,7 +57,7 @@ func (g *ginFramework) PATCH(path string, handler framework.FrameworkHandler) {
5657

5758
func (g *ginFramework) DELETE(path string, handler framework.FrameworkHandler) {
5859
g.engine.DELETE(path, func(c *gin.Context) {
59-
err := handler(NewRequest(c), NewResponse(c))
60+
err := handler(NewRequest(c), NewResponse(c), context.New())
6061
if err != nil {
6162
c.AbortWithError(http.StatusInternalServerError, err)
6263
}
@@ -65,7 +66,7 @@ func (g *ginFramework) DELETE(path string, handler framework.FrameworkHandler) {
6566

6667
func (g *ginFramework) OPTIONS(path string, handler framework.FrameworkHandler) {
6768
g.engine.OPTIONS(path, func(c *gin.Context) {
68-
err := handler(NewRequest(c), NewResponse(c))
69+
err := handler(NewRequest(c), NewResponse(c), context.New())
6970
if err != nil {
7071
c.AbortWithError(http.StatusInternalServerError, err)
7172
}
@@ -74,7 +75,7 @@ func (g *ginFramework) OPTIONS(path string, handler framework.FrameworkHandler)
7475

7576
func (g *ginFramework) HEAD(path string, handler framework.FrameworkHandler) {
7677
g.engine.HEAD(path, func(c *gin.Context) {
77-
err := handler(NewRequest(c), NewResponse(c))
78+
err := handler(NewRequest(c), NewResponse(c), context.New())
7879
if err != nil {
7980
c.AbortWithError(http.StatusInternalServerError, err)
8081
}
@@ -83,7 +84,7 @@ func (g *ginFramework) HEAD(path string, handler framework.FrameworkHandler) {
8384

8485
func (g *ginFramework) TRACE(path string, handler framework.FrameworkHandler) {
8586
g.engine.Handle("TRACE", path, func(c *gin.Context) {
86-
err := handler(NewRequest(c), NewResponse(c))
87+
err := handler(NewRequest(c), NewResponse(c), context.New())
8788
if err != nil {
8889
c.AbortWithError(http.StatusInternalServerError, err)
8990
}

pkg/framework/iface.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package framework
33
import (
44
"mime/multipart"
55
"net/http"
6+
7+
"github.com/go-simpl/simplapi/pkg/context"
68
)
79

810
type Framework interface {
@@ -19,7 +21,7 @@ type Framework interface {
1921
TestRequest(req *http.Request) (*http.Response, error)
2022
}
2123

22-
type FrameworkHandler func(req FrameworkRequest, res FrameworkResponse) error
24+
type FrameworkHandler func(req FrameworkRequest, res FrameworkResponse, ctx *context.Context) error
2325

2426
type FrameworkRequest interface {
2527
ParseJSONBody(target interface{}) error

pkg/handler/main.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"reflect"
66

77
"github.com/go-simpl/simplapi/errors"
8+
"github.com/go-simpl/simplapi/pkg/context"
89
"github.com/go-simpl/simplapi/pkg/framework"
910
"github.com/go-simpl/simplapi/pkg/reflection"
1011
"github.com/go-simpl/simplapi/types"
@@ -29,10 +30,15 @@ func WrapHandler(handler interface{}, next framework.FrameworkHandler) framework
2930
panic("handler must return an error at the last position")
3031
}
3132

32-
createParams := func(req framework.FrameworkRequest) ([]reflect.Value, error) {
33+
createParams := func(req framework.FrameworkRequest, ctx *context.Context) ([]reflect.Value, error) {
3334
numInputs := handlerType.NumIn()
3435
inputs := make([]reflect.Value, numInputs)
3536
for i := 0; i < numInputs; i++ {
37+
if handlerType.In(i) == reflect.TypeOf(ctx) {
38+
inputs[i] = reflect.ValueOf(ctx)
39+
continue
40+
}
41+
3642
inputs[i] = reflect.New(handlerType.In(i)).Elem()
3743
err := reflection.PopulateValueFromTypeUsingContext(req, handlerType.In(i), inputs[i])
3844
if err != nil {
@@ -42,8 +48,8 @@ func WrapHandler(handler interface{}, next framework.FrameworkHandler) framework
4248
return inputs, nil
4349
}
4450

45-
return func(req framework.FrameworkRequest, res framework.FrameworkResponse) error {
46-
inputs, err := createParams(req)
51+
return func(req framework.FrameworkRequest, res framework.FrameworkResponse, ctx *context.Context) error {
52+
inputs, err := createParams(req, ctx)
4753
if err != nil {
4854
if typeErr, ok := err.(errors.TypeError); ok {
4955
res.SetStatusCode(http.StatusUnprocessableEntity)
@@ -79,7 +85,7 @@ func WrapHandler(handler interface{}, next framework.FrameworkHandler) framework
7985
}
8086

8187
if next != nil {
82-
return next(req, res)
88+
return next(req, res, ctx)
8389
}
8490

8591
return nil

pkg/swagger/helper.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"reflect"
88
"strings"
99

10+
"github.com/go-simpl/simplapi/pkg/context"
1011
"github.com/go-simpl/simplapi/types"
1112
)
1213

@@ -28,6 +29,10 @@ func UpdateDefinitionUsingParamTypes(definition map[string]interface{}, paramTyp
2829
HEADER_EXCLUSIONS := map[string]bool{"content-type": true, "content-length": true, "user-agent": true}
2930

3031
for _, paramType := range paramTypes {
32+
if paramType == reflect.TypeOf((*context.Context)(nil)) {
33+
continue
34+
}
35+
3136
for i := 0; i < paramType.NumField(); i++ {
3237
field := paramType.Field(i)
3338
if field.Tag.Get("body") != "" {

tests/chain_tests/chain_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ import (
44
"errors"
55
"io"
66
"net/http"
7+
"net/http/httptest"
78
"testing"
89

910
"github.com/stretchr/testify/assert"
1011

1112
"github.com/go-simpl/simplapi"
13+
"github.com/go-simpl/simplapi/pkg/context"
1214

1315
_ "github.com/go-simpl/simplapi/pkg/framework/fiberframework"
1416
)
@@ -127,3 +129,32 @@ func TestChainReturnedErrorFromFirstFunc(t *testing.T) {
127129
bodyString := string(bodyBytes)
128130
assert.Equal(t, `server error`, bodyString)
129131
}
132+
133+
func TestContextInChain(t *testing.T) {
134+
app := simplapi.New()
135+
fApp := app.GetApp()
136+
137+
func1 := func(ctx *context.Context) (*HelloResponse, error) {
138+
ctx.Set("test", "test")
139+
return nil, nil
140+
}
141+
142+
func2 := func(ctx *context.Context) (*HelloResponse, error) {
143+
assert.Equal(t, "test", ctx.Get("test"))
144+
ctx.Delete("test")
145+
return nil, nil
146+
}
147+
148+
func3 := func(ctx *context.Context) (*HelloResponse, error) {
149+
assert.False(t, ctx.Contains("test"))
150+
return &HelloResponse{Message: ""}, nil
151+
}
152+
153+
app.GET("/", nil, func1, func2, func3)
154+
155+
req := httptest.NewRequest("GET", "/", nil)
156+
response, err := fApp.TestRequest(req)
157+
assert.NoError(t, err)
158+
159+
assert.Equal(t, http.StatusOK, response.StatusCode)
160+
}

0 commit comments

Comments
 (0)