Add GenericValues Parse

This commit is contained in:
some 2024-10-08 17:57:25 -04:00
parent 7e1453e72f
commit 6c278caa29
Signed by: some
GPG Key ID: 65D0589220B9BFC8
5 changed files with 66 additions and 47 deletions

41
common.go Normal file
View File

@ -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
}
}

View File

@ -1,44 +1,13 @@
package router package router
import ( import (
"fmt"
"reflect"
"strings" "strings"
) )
type Header map[string][]string type Header map[string][]string
func (h Header) Parse(data any) { func (h Header) Parse(data any) {
if h == nil { GenericValues(h).Parse(data, "header")
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
}
} }
func (h Header) Get(key string) (value string) { func (h Header) Get(key string) (value string) {

View File

@ -2,15 +2,18 @@ package router
import "io" import "io"
type Request interface { type RequestBuilder interface {
Allowed(method string) ErrorResponse Allowed(method string) ErrorResponse
Header() Header Header(Header) ErrorResponse
ReadBody(body io.ReadCloser) ErrorResponse Body(body io.ReadCloser) ErrorResponse
ParseForm(values map[string][]string) ErrorResponse Values(values Values) ErrorResponse
AllowedError() ErrorResponse
ReadError() ErrorResponse
ParseError() ErrorResponse
} }
type PrototypeRequest interface { type PrototypeRequestBuilder interface {
Request() Request RequestBuilder() RequestBuilder
} }
type Response interface { type Response interface {
@ -32,13 +35,10 @@ type ErrorResponse interface {
type PrototypeErrorResponse interface { type PrototypeErrorResponse interface {
ErrorResponse() ErrorResponse ErrorResponse() ErrorResponse
AllowedError() ErrorResponse
ReadError() ErrorResponse
ParseError() ErrorResponse
} }
type Prototype struct { type Prototype struct {
PrototypeRequest PrototypeRequestBuilder
PrototypeResponse PrototypeResponse
PrototypeErrorResponse PrototypeErrorResponse
} }

View File

@ -15,7 +15,7 @@ const (
numStages numStages
) )
type ServeFunc func(req Request, res Response) (errRes ErrorResponse) type ServeFunc func(req RequestBuilder, res Response) (errRes ErrorResponse)
type server struct { type server struct {
prototype Prototype 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) { func (srv *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
pro := srv.prototype pro := srv.prototype
req := pro.Request() req := pro.RequestBuilder()
if ok := srv.handleError(req.Allowed(r.Method), w); !ok { if ok := srv.handleError(req.Allowed(r.Method), w); !ok {
return return
} }
req.Header().MergeOverwrite(Header(r.Header)) if ok := srv.handleError(req.Header(Header(r.Header)), w); !ok {
if ok := srv.handleError(req.ReadBody(r.Body), w); !ok { return
}
if ok := srv.handleError(req.Body(r.Body), w); !ok {
return return
} }
r.ParseForm() r.ParseForm()
if ok := srv.handleError(req.ParseForm(r.Form), w); !ok { if ok := srv.handleError(req.Values(Values(r.Form)), w); !ok {
return return
} }
res := pro.Response() res := pro.Response()

7
values.go Normal file
View File

@ -0,0 +1,7 @@
package router
type Values map[string][]string
func (v Values) Parse(data any) {
GenericValues(v).Parse(data, "form")
}