Skip to content

Commit 9d67066

Browse files
authored
Merge pull request #18
ext-request-validation
2 parents 10a422b + 6801b21 commit 9d67066

File tree

4 files changed

+73
-19
lines changed

4 files changed

+73
-19
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,16 @@
33
All notable changes to the "Go-Web Framework" will be documented in this file.
44

55
## [Unreleased]
6+
7+
8+
## [v0.7.1-beta] - 2021-09-02
69
### Fixed
710
- Issue #17
811
- Issue #16
912

13+
### Added
14+
- Support for request validation in routers
15+
-
1016
## [v0.7.0-beta] - 2021-08-27
1117
### Changed
1218
- Changed .yml routing system in favour of the router module. Now every route/group have to be registered directly in go structure.

kernel/router.go

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ type Route struct {
1717
Action string
1818
Method string
1919
Description string
20+
Validation interface{}
2021
Middleware []Middleware
2122
}
2223

@@ -62,16 +63,31 @@ func HandleSingleRoute(routes []Route, router *mux.Router) {
6263
for _, route := range routes {
6364
hasMiddleware := len(route.Middleware) > 0
6465
directive := strings.Split(route.Action, "@")
66+
validation := route.Validation
6567
if hasMiddleware {
6668
subRouter := mux.NewRouter()
6769
subRouter.HandleFunc(route.Path, func(writer http.ResponseWriter, request *http.Request) {
70+
if err := validateRequest(validation, request); err != nil {
71+
writer.WriteHeader(http.StatusUnprocessableEntity)
72+
_, _ = writer.Write([]byte(err.Error()))
73+
74+
return
75+
}
76+
6877
executeControllerDirective(directive, writer, request)
6978
}).Methods(route.Method)
7079

7180
subRouter.Use(parseMiddleware(route.Middleware)...)
7281
router.Handle(route.Path, subRouter).Methods(route.Method)
7382
} else {
7483
router.HandleFunc(route.Path, func(writer http.ResponseWriter, request *http.Request) {
84+
if err := validateRequest(validation, request); err != nil {
85+
writer.WriteHeader(http.StatusUnprocessableEntity)
86+
_, _ = writer.Write([]byte(err.Error()))
87+
88+
return
89+
}
90+
7591
executeControllerDirective(directive, writer, request)
7692
}).Methods(route.Method)
7793
}
@@ -85,17 +101,32 @@ func HandleGroups(groups []Group, router *mux.Router) {
85101

86102
for _, route := range group.Routes {
87103
directive := strings.Split(route.Action, "@")
104+
validation := route.Validation
88105
if len(route.Middleware) > 0 {
89106
nestedRouter := mux.NewRouter()
90107
fullPath := fmt.Sprintf("%s%s", group.Prefix, route.Path)
91108
nestedRouter.HandleFunc(fullPath, func(writer http.ResponseWriter, request *http.Request) {
109+
if err := validateRequest(validation, request); err != nil {
110+
writer.WriteHeader(http.StatusUnprocessableEntity)
111+
_, _ = writer.Write([]byte(err.Error()))
112+
113+
return
114+
}
115+
92116
executeControllerDirective(directive, writer, request)
93117
}).Methods(route.Method)
94118

95119
nestedRouter.Use(parseMiddleware(route.Middleware)...)
96120
subRouter.Handle(route.Path, nestedRouter).Methods(route.Method)
97121
} else {
98122
subRouter.HandleFunc(route.Path, func(writer http.ResponseWriter, request *http.Request) {
123+
if err := validateRequest(validation, request); err != nil {
124+
writer.WriteHeader(http.StatusUnprocessableEntity)
125+
_, _ = writer.Write([]byte(err.Error()))
126+
127+
return
128+
}
129+
99130
executeControllerDirective(directive, writer, request)
100131
}).Methods(route.Method)
101132
}
@@ -132,12 +163,26 @@ func GetControllerInterface(directive []string, w http.ResponseWriter, r *http.R
132163
// Example: MainController@main
133164
// executes the main method from MainController
134165
// It build the CUSTOM SERVICE CONTAINER and invoke the selected directive inside them.
135-
func executeControllerDirective(directive []string, w http.ResponseWriter, r *http.Request) {
166+
func executeControllerDirective(d []string, w http.ResponseWriter, r *http.Request) {
136167
container := BuildCustomContainer()
137-
cc := GetControllerInterface(directive, w, r)
138-
method := reflect.ValueOf(cc).MethodByName(directive[1])
168+
cc := GetControllerInterface(d, w, r)
169+
method := reflect.ValueOf(cc).MethodByName(d[1])
139170

140171
if err := dig.GroupInvoke(method.Interface(), container, SingletonIOC); err != nil {
141172
log.Fatal(err)
142173
}
143174
}
175+
176+
func validateRequest(data interface{}, r *http.Request) error {
177+
if data != nil {
178+
if err := tool.DecodeJsonRequest(r, &data); err != nil {
179+
return err
180+
}
181+
182+
if err := tool.ValidateRequest(data); err != nil {
183+
return err
184+
}
185+
}
186+
187+
return nil
188+
}

tool/json.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,30 @@
11
package tool
22

33
import (
4+
"bytes"
45
"encoding/json"
6+
"errors"
7+
"io"
8+
"io/ioutil"
59
"net/http"
610
)
711

812
// DecodeJsonRequest in a selected struct
913
func DecodeJsonRequest(r *http.Request, interfaceRef interface{}) error {
10-
decoder := json.NewDecoder(r.Body)
11-
if err := decoder.Decode(interfaceRef); err != nil {
14+
data, err := ioutil.ReadAll(r.Body)
15+
if err != nil {
1216
return err
1317
}
1418

19+
if err := json.Unmarshal(data, interfaceRef); err != nil {
20+
if err == io.EOF {
21+
return errors.New("missing request body")
22+
}
23+
24+
return err
25+
}
26+
27+
r.Body = ioutil.NopCloser(bytes.NewBuffer(data))
28+
1529
return nil
1630
}

tool/validation.go

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,14 @@
11
package tool
22

33
import (
4-
"encoding/json"
54
"gopkg.in/asaskevich/govalidator.v4"
6-
"log"
7-
"net/http"
85
)
96

107
// ValidateRequest incoming request
11-
func ValidateRequest(data interface{}, response http.ResponseWriter) bool {
8+
func ValidateRequest(data interface{}) error {
129
if valid, err := govalidator.ValidateStruct(data); valid == false {
13-
message, e := json.Marshal(err)
14-
15-
if e != nil {
16-
log.Fatal(err)
17-
}
18-
19-
response.WriteHeader(422)
20-
_, _ = response.Write(message)
21-
return false
10+
return err
2211
}
2312

24-
return true
13+
return nil
2514
}

0 commit comments

Comments
 (0)