Attempt to implement default methods

This commit is contained in:
some 2024-10-08 22:30:29 -04:00
parent 89a0f458c7
commit 84a91d56eb
Signed by: some
GPG Key ID: 65D0589220B9BFC8
6 changed files with 191 additions and 129 deletions

9
body.go Normal file
View File

@ -0,0 +1,9 @@
package router
type body interface {
mustEmbedBody()
}
type Body []byte
func (Body) mustEmbedBody() {}

View File

@ -12,6 +12,9 @@ func (gv genericValues) Parse(data any, tag string) (err error) {
gv = make(genericValues)
}
d := reflect.ValueOf(data)
if d.Kind() == reflect.Pointer || d.Kind() == reflect.Interface {
d = d.Elem()
}
if d.Kind() != reflect.Struct {
err = fmt.Errorf("expected struct input for data")
return

167
default.go Normal file
View File

@ -0,0 +1,167 @@
package router
import (
"encoding/json"
"fmt"
"io"
"net/http"
)
type DefaultError uint32
const (
DefaultOk DefaultError = http.StatusOK
DefaultErrorNotImplemented DefaultError = http.StatusNotImplemented
DefaultErrorMethodNotAllowed DefaultError = http.StatusMethodNotAllowed
DefaultErrorBadRequest DefaultError = http.StatusBadRequest
DefaultErrorUnauthorized DefaultError = http.StatusUnauthorized
DefaultErrorServerError DefaultError = http.StatusInternalServerError
)
func (e DefaultError) Ok() (ok bool) {
return e == DefaultOk
}
func (e DefaultError) HttpStatus() (code int) {
return int(e)
}
func (e DefaultError) String() (out string) {
switch e {
case DefaultOk:
out = "ok"
case DefaultErrorNotImplemented:
out = "server not implemented"
case DefaultErrorMethodNotAllowed:
out = "method not allowed"
case DefaultErrorBadRequest:
out = "bad request"
case DefaultErrorUnauthorized:
out = "user unauthorized"
case DefaultErrorServerError:
out = "internal server error"
default:
out = "unhandled error"
}
return
}
func (e DefaultError) Error() (out string) {
return fmt.Sprintf("%s (%d)", e.String(), e.HttpStatus())
}
func (e DefaultError) BodyBytes() (body []byte) {
body, _ = json.Marshal(struct{ Error string }{Error: e.String()})
return
}
type DefaultRequestBuilder struct {
requestBuilder RequestBuilder
allowedMethods *[]string
header struct {
*Header
fields *header
}
values struct {
*Values
fields *values
}
body struct {
*Body
fields *body
}
}
func NewDefaultRequestBuilder(rb RequestBuilder, am *[]string, h *Header, hf *header, v *Values, vf *values, b *Body, bf *body) DefaultRequestBuilder {
return DefaultRequestBuilder{
requestBuilder: rb,
allowedMethods: am,
header: struct {
*Header
fields *header
}{
Header: h,
fields: hf,
},
values: struct {
*Values
fields *values
}{
Values: v,
fields: vf,
},
body: struct {
*Body
fields *body
}{
Body: b,
fields: bf,
},
}
}
func (rb DefaultRequestBuilder) RequestBuilder() RequestBuilder {
return rb.requestBuilder
}
func (rb *DefaultRequestBuilder) Allowed(method string) (errRes ErrorResponse) {
var ok bool
for _, m := range *rb.allowedMethods {
if m == method {
ok = true
}
}
if !ok {
return DefaultErrorMethodNotAllowed
}
return DefaultOk
}
func (rb *DefaultRequestBuilder) Header(header Header) (errRes ErrorResponse) {
err := rb.header.Header.Parse(header)
if err != nil {
return DefaultErrorBadRequest
}
return DefaultOk
}
func (rb *DefaultRequestBuilder) ReadBody(body io.ReadCloser) (errRes ErrorResponse) {
defer body.Close()
json.NewDecoder(body).Decode(rb.body.fields)
return DefaultOk
}
func (rb *DefaultRequestBuilder) Values(values Values) (errRes ErrorResponse) {
err := rb.values.Values.Parse(values)
if err != nil {
return DefaultErrorBadRequest
}
return DefaultOk
}
type DefaultResponse struct {
header struct {
*Header
fields *header
}
body struct {
*Body
fields *body
}
}
func (r DefaultResponse) Response() Response {
return &r
}
func (r *DefaultResponse) Header() (header Header) {
if r.header.Header == nil {
r.header.Header.Parse(r.header.fields)
}
return *r.header.Header
}
func (r *DefaultResponse) BodyBytes() (body []byte) {
body, _ = json.Marshal(r.body.fields)
return
}

View File

@ -4,8 +4,14 @@ import (
"strings"
)
type header interface {
mustEmbedHeader()
}
type Header map[string][]string
func (Header) mustEmbedHeader() {}
func (h Header) Parse(data any) error {
return genericValues(h).Parse(data, "header")
}

View File

@ -1,129 +0,0 @@
package router
import (
"encoding/json"
"fmt"
"io"
"net/http"
)
type UnimplementedError uint32
const (
UnimplementedOk UnimplementedError = http.StatusOK
UnimplementedErrorNotImplemented UnimplementedError = http.StatusNotImplemented
UnimplementedErrorMethodNotAllowed UnimplementedError = http.StatusMethodNotAllowed
UnimplementedErrorBadRequest UnimplementedError = http.StatusBadRequest
UnimplementedErrorUnauthorized UnimplementedError = http.StatusUnauthorized
UnimplementedErrorServerError UnimplementedError = http.StatusInternalServerError
)
func (e UnimplementedError) Ok() (ok bool) {
return e == UnimplementedOk
}
func (e UnimplementedError) HttpStatus() (code int) {
return int(e)
}
func (e UnimplementedError) String() (out string) {
switch e {
case UnimplementedOk:
out = "ok"
case UnimplementedErrorNotImplemented:
out = "server not implemented"
case UnimplementedErrorMethodNotAllowed:
out = "method not allowed"
case UnimplementedErrorBadRequest:
out = "bad request"
case UnimplementedErrorUnauthorized:
out = "user unauthorized"
case UnimplementedErrorServerError:
out = "internal server error"
default:
out = "unhandled error"
}
return
}
func (e UnimplementedError) Error() (out string) {
return fmt.Sprintf("%s (%d)", e.String(), e.HttpStatus())
}
func (e UnimplementedError) BodyBytes() (body []byte) {
body, _ = json.Marshal(struct{ Error string }{Error: e.String()})
return
}
type UnimplementedRequestBuilder struct {
allowedMethods []string
header struct {
Header
}
values struct {
Values
}
Body struct{}
}
func (rb UnimplementedRequestBuilder) RequestBuilder() RequestBuilder {
return &rb
}
func (rb *UnimplementedRequestBuilder) Allowed(method string) (errRes ErrorResponse) {
var ok bool
for _, m := range rb.allowedMethods {
if m == method {
ok = true
}
}
if !ok {
return UnimplementedErrorMethodNotAllowed
}
return UnimplementedOk
}
func (rb *UnimplementedRequestBuilder) Header(header Header) (errRes ErrorResponse) {
err := rb.header.Header.Parse(header)
if err != nil {
return UnimplementedErrorBadRequest
}
return UnimplementedOk
}
func (rb *UnimplementedRequestBuilder) ReadBody(body io.ReadCloser) (errRes ErrorResponse) {
defer body.Close()
json.NewDecoder(body).Decode(&rb.Body)
return UnimplementedOk
}
func (rb *UnimplementedRequestBuilder) Values(values Values) (errRes ErrorResponse) {
err := rb.values.Values.Parse(values)
if err != nil {
return UnimplementedErrorBadRequest
}
return UnimplementedOk
}
type UnimplementedResponse struct {
header struct {
Header
}
Body struct{}
}
func (r UnimplementedResponse) Response() Response {
return &r
}
func (r *UnimplementedResponse) Header() (header Header) {
if r.header.Header == nil {
r.header.Header.Parse(r.header)
}
return r.header.Header
}
func (r *UnimplementedResponse) BodyBytes() (body []byte) {
body, _ = json.Marshal(r.Body)
return
}

View File

@ -1,7 +1,13 @@
package router
type values interface {
mustEmbedValues()
}
type Values map[string][]string
func (Values) mustEmbedValues() {}
func (v Values) Parse(data any) error {
return genericValues(v).Parse(data, "form")
}