diff --git a/common.go b/common.go new file mode 100644 index 0000000..fca9607 --- /dev/null +++ b/common.go @@ -0,0 +1,41 @@ +package router + +import ( + "fmt" + "reflect" +) + +type GenericValues map[string][]string + +func (gv GenericValues) Parse(data any, tag string) { + if gv == nil { + gv = make(GenericValues) + } + d := reflect.ValueOf(data) + if d.Kind() != reflect.Struct { + panic(fmt.Errorf("expected struct input for data")) + } + for i := 0; i < d.NumField(); i++ { + key, ok := d.Type().Field(i).Tag.Lookup(tag) + if !ok || key == "" { + continue + } + v := make([]string, 0) + val := d.Field(i) + if val.Kind() == reflect.Pointer || val.Kind() == reflect.Interface { + val = val.Elem() + } + if val.Kind() == reflect.Slice || val.Kind() == reflect.Array { + for j := 0; j < val.Len(); j++ { + item := val.Index(j) + if item.Kind() == reflect.Pointer || item.Kind() == reflect.Interface { + item = item.Elem() + } + v = append(v, fmt.Sprintf("%s", item.Interface())) + } + } else { + v = append(v, fmt.Sprintf("%s", val.Interface())) + } + gv[key] = v + } +} diff --git a/header.go b/header.go index 0bc5bc0..f175110 100644 --- a/header.go +++ b/header.go @@ -1,44 +1,13 @@ package router import ( - "fmt" - "reflect" "strings" ) type Header map[string][]string func (h Header) Parse(data any) { - if h == nil { - h = make(Header) - } - d := reflect.ValueOf(data) - if d.Kind() != reflect.Struct { - panic(fmt.Errorf("expected struct input for data")) - } - for i := 0; i < d.NumField(); i++ { - key, ok := d.Type().Field(i).Tag.Lookup("header") - if !ok || key == "" { - continue - } - v := make([]string, 0) - val := d.Field(i) - if val.Kind() == reflect.Pointer || val.Kind() == reflect.Interface { - val = val.Elem() - } - if val.Kind() == reflect.Slice || val.Kind() == reflect.Array { - for j := 0; j < val.Len(); j++ { - item := val.Index(j) - if item.Kind() == reflect.Pointer || item.Kind() == reflect.Interface { - item = item.Elem() - } - v = append(v, fmt.Sprintf("%s", item.Interface())) - } - } else { - v = append(v, fmt.Sprintf("%s", val.Interface())) - } - h[key] = v - } + GenericValues(h).Parse(data, "header") } func (h Header) Get(key string) (value string) { diff --git a/prototype.go b/prototype.go index 1e7f9d7..cb0a15a 100644 --- a/prototype.go +++ b/prototype.go @@ -2,15 +2,18 @@ package router import "io" -type Request interface { +type RequestBuilder interface { Allowed(method string) ErrorResponse - Header() Header - ReadBody(body io.ReadCloser) ErrorResponse - ParseForm(values map[string][]string) ErrorResponse + Header(Header) ErrorResponse + Body(body io.ReadCloser) ErrorResponse + Values(values Values) ErrorResponse + AllowedError() ErrorResponse + ReadError() ErrorResponse + ParseError() ErrorResponse } -type PrototypeRequest interface { - Request() Request +type PrototypeRequestBuilder interface { + RequestBuilder() RequestBuilder } type Response interface { @@ -32,13 +35,10 @@ type ErrorResponse interface { type PrototypeErrorResponse interface { ErrorResponse() ErrorResponse - AllowedError() ErrorResponse - ReadError() ErrorResponse - ParseError() ErrorResponse } type Prototype struct { - PrototypeRequest + PrototypeRequestBuilder PrototypeResponse PrototypeErrorResponse } diff --git a/server.go b/server.go index 9bf955c..2892c61 100644 --- a/server.go +++ b/server.go @@ -15,7 +15,7 @@ const ( numStages ) -type ServeFunc func(req Request, res Response) (errRes ErrorResponse) +type ServeFunc func(req RequestBuilder, res Response) (errRes ErrorResponse) type server struct { prototype Prototype @@ -65,16 +65,18 @@ func (srv *server) handleError(errRes ErrorResponse, w http.ResponseWriter) (ok func (srv *server) ServeHTTP(w http.ResponseWriter, r *http.Request) { pro := srv.prototype - req := pro.Request() + req := pro.RequestBuilder() if ok := srv.handleError(req.Allowed(r.Method), w); !ok { return } - req.Header().MergeOverwrite(Header(r.Header)) - if ok := srv.handleError(req.ReadBody(r.Body), w); !ok { + if ok := srv.handleError(req.Header(Header(r.Header)), w); !ok { + return + } + if ok := srv.handleError(req.Body(r.Body), w); !ok { return } r.ParseForm() - if ok := srv.handleError(req.ParseForm(r.Form), w); !ok { + if ok := srv.handleError(req.Values(Values(r.Form)), w); !ok { return } res := pro.Response() diff --git a/values.go b/values.go new file mode 100644 index 0000000..050efa5 --- /dev/null +++ b/values.go @@ -0,0 +1,7 @@ +package router + +type Values map[string][]string + +func (v Values) Parse(data any) { + GenericValues(v).Parse(data, "form") +}