Skip to content

Commit ce92290

Browse files
committed
fix: implement parameter construction and response transfer for framework handlers
1 parent 6096b0c commit ce92290

5 files changed

Lines changed: 67 additions & 31 deletions

File tree

ROADMAP.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
## Features
44

5+
- [ ] Configurable Swagger Spec
6+
- [ ] Swagger descriptions
57
- [ ] Response Headers
68
- [ ] Non-json responses
79
- [ ] Middleware
810
- [ ] Response Cookies
911
- [ ] Streaming responses
12+
- [ ] Native handler
1013

1114
## Framework support
1215

pkg/handler/inputParams.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package handler
2+
3+
import (
4+
"reflect"
5+
6+
"github.com/go-simpl/simplapi/pkg/context"
7+
"github.com/go-simpl/simplapi/pkg/framework"
8+
"github.com/go-simpl/simplapi/pkg/reflection"
9+
)
10+
11+
func constructParams(req framework.FrameworkRequest, ctx *context.Context, handlerInputTypes []reflect.Type) ([]reflect.Value, error) {
12+
numInputs := len(handlerInputTypes)
13+
inputs := make([]reflect.Value, numInputs)
14+
for i := 0; i < numInputs; i++ {
15+
if handlerInputTypes[i] == reflect.TypeOf(ctx) {
16+
inputs[i] = reflect.ValueOf(ctx)
17+
continue
18+
}
19+
20+
inputs[i] = reflect.New(handlerInputTypes[i]).Elem()
21+
err := reflection.ComputeValuesFromRequest(req, handlerInputTypes[i], inputs[i])
22+
if err != nil {
23+
return nil, err
24+
}
25+
}
26+
return inputs, nil
27+
}

pkg/handler/main.go

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ import (
77
"github.com/go-simpl/simplapi/errors"
88
"github.com/go-simpl/simplapi/pkg/context"
99
"github.com/go-simpl/simplapi/pkg/framework"
10-
"github.com/go-simpl/simplapi/pkg/reflection"
11-
"github.com/go-simpl/simplapi/types"
1210
)
1311

1412
func WrapHandler(handler interface{}, next framework.FrameworkHandler) framework.FrameworkHandler {
@@ -30,26 +28,13 @@ func WrapHandler(handler interface{}, next framework.FrameworkHandler) framework
3028
panic("handler must return an error at the last position")
3129
}
3230

33-
createParams := func(req framework.FrameworkRequest, ctx *context.Context) ([]reflect.Value, error) {
34-
numInputs := handlerType.NumIn()
35-
inputs := make([]reflect.Value, numInputs)
36-
for i := 0; i < numInputs; i++ {
37-
if handlerType.In(i) == reflect.TypeOf(ctx) {
38-
inputs[i] = reflect.ValueOf(ctx)
39-
continue
40-
}
41-
42-
inputs[i] = reflect.New(handlerType.In(i)).Elem()
43-
err := reflection.PopulateValueFromTypeUsingContext(req, handlerType.In(i), inputs[i])
44-
if err != nil {
45-
return nil, err
46-
}
47-
}
48-
return inputs, nil
31+
handlerInputTypes := make([]reflect.Type, handlerType.NumIn())
32+
for i := 0; i < handlerType.NumIn(); i++ {
33+
handlerInputTypes[i] = handlerType.In(i)
4934
}
5035

5136
return func(req framework.FrameworkRequest, res framework.FrameworkResponse, ctx *context.Context) error {
52-
inputs, err := createParams(req, ctx)
37+
inputs, err := constructParams(req, ctx, handlerInputTypes)
5338
if err != nil {
5439
if typeErr, ok := err.(errors.TypeError); ok {
5540
res.SetStatusCode(http.StatusUnprocessableEntity)
@@ -68,19 +53,15 @@ func WrapHandler(handler interface{}, next framework.FrameworkHandler) framework
6853
// handle response
6954
for _, result := range results {
7055
if !result.IsNil() {
71-
// check for custom response types
72-
if response, ok := result.Interface().(*types.HTMLResponse); ok {
73-
res.SetStatusCode(http.StatusOK)
74-
res.SetHeader("Content-Type", "text/html")
75-
return res.SendString(response.HTML)
56+
bodyDone, err := transferToResponse(res, result)
57+
if err != nil {
58+
return err
7659
}
7760

78-
if response, ok := result.Interface().(types.APIResponse); ok {
79-
res.SetStatusCode(response.GetStatusCode())
80-
return res.SendJSON(result.Interface())
81-
} else {
82-
return res.SendJSON(result.Interface())
61+
if bodyDone {
62+
return nil
8363
}
64+
8465
}
8566
}
8667

pkg/handler/transferToResponse.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package handler
2+
3+
import (
4+
"net/http"
5+
"reflect"
6+
7+
"github.com/go-simpl/simplapi/pkg/framework"
8+
"github.com/go-simpl/simplapi/types"
9+
)
10+
11+
func transferToResponse(res framework.FrameworkResponse, result reflect.Value) (bool, error) {
12+
// check for custom response types
13+
if response, ok := result.Interface().(*types.HTMLResponse); ok {
14+
res.SetStatusCode(http.StatusOK)
15+
res.SetHeader("Content-Type", "text/html")
16+
return true, res.SendString(response.HTML)
17+
}
18+
19+
if response, ok := result.Interface().(types.APIResponse); ok {
20+
res.SetStatusCode(response.GetStatusCode())
21+
return true, res.SendJSON(result.Interface())
22+
} else {
23+
return true, res.SendJSON(result.Interface())
24+
}
25+
}

pkg/reflection/reflection.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
"github.com/go-simpl/simplapi/pkg/framework"
1111
)
1212

13-
func PopulateValueFromTypeUsingContext(f framework.FrameworkRequest, pType reflect.Type, pVal reflect.Value) error {
13+
func ComputeValuesFromRequest(f framework.FrameworkRequest, pType reflect.Type, pVal reflect.Value) error {
1414
for i := 0; i < pVal.NumField(); i++ {
1515
if pType.Field(i).Tag.Get("body") == "json" {
1616
b := pVal.Field(i).Addr().Interface()
@@ -52,7 +52,7 @@ func PopulateValueFromTypeUsingContext(f framework.FrameworkRequest, pType refle
5252
}
5353

5454
} else if pType.Field(i).Type.Kind() == reflect.Struct {
55-
err := PopulateValueFromTypeUsingContext(f, pType.Field(i).Type, pVal.Field(i))
55+
err := ComputeValuesFromRequest(f, pType.Field(i).Type, pVal.Field(i))
5656
if err != nil {
5757
return err
5858
}

0 commit comments

Comments
 (0)