Add back ResponseBuilder

This commit is contained in:
some 2024-10-10 14:59:55 -04:00
parent 8c8976d79a
commit 052eb1ed56
Signed by: some
GPG Key ID: 65D0589220B9BFC8
2 changed files with 131 additions and 25 deletions

View File

@ -43,12 +43,12 @@ func (e DefaultError) String() (out string) {
return return
} }
func (e DefaultError) Response() *Response { func (e DefaultError) Response() *response {
body, err := json.Marshal(struct{ Error string }{Error: e.String()}) body, err := json.Marshal(struct{ Error string }{Error: e.String()})
if err != nil { if err != nil {
panic(err) panic(err)
} }
return &Response{ return &response{
Status: e.Status(), Status: e.Status(),
Header: Header{"Content-Type": []string{"text/javascript", "charset=utf-8"}}, Header: Header{"Content-Type": []string{"text/javascript", "charset=utf-8"}},
Body: body, Body: body,
@ -81,7 +81,7 @@ type DefaultRequestBuilder struct {
} }
} }
// /* Leave commented to require services to create their own New method */ // Leave commented to require services to create their own New method
// var _ RequestBuilder = (*DefaultRequestBuilder)(nil) // var _ RequestBuilder = (*DefaultRequestBuilder)(nil)
// func (*DefaultRequestBuilder) New() RequestBuilder { // func (*DefaultRequestBuilder) New() RequestBuilder {
// return NewDefaultRequestBuilder() // return NewDefaultRequestBuilder()
@ -177,7 +177,7 @@ func (rqb *DefaultRequestBuilder) Url(url url.URL) (e Error) {
return return
} }
func (rqb *DefaultRequestBuilder) Header(header Header) (e Error) { func (rqb *DefaultRequestBuilder) Header(header map[string][]string) (e Error) {
*rqb.header.Header = header *rqb.header.Header = header
err := rqb.header.Header.Unmarshal(rqb.header.fields) err := rqb.header.Header.Unmarshal(rqb.header.fields)
if err != nil { if err != nil {
@ -192,7 +192,7 @@ func (rqb *DefaultRequestBuilder) Body(body io.ReadCloser) (e Error) {
return return
} }
func (rqb *DefaultRequestBuilder) Values(values Values) (e Error) { func (rqb *DefaultRequestBuilder) Values(values map[string][]string) (e Error) {
*rqb.values.Values = values *rqb.values.Values = values
err := rqb.values.Values.Unmarshal(rqb.values.fields) err := rqb.values.Values.Unmarshal(rqb.values.fields)
if err != nil { if err != nil {
@ -210,3 +210,88 @@ func (rqb *DefaultRequestBuilder) Request() (req *request) {
} }
return return
} }
type DefaultResponseBuilder struct {
errorHandler Error
status *int
header struct {
*Header
fields header
}
body struct {
*Body
fields body
}
}
// Leave commented to require services to create their own New method
// var _ ResponseBuilder = (*DefaultResponseBuilder)(nil)
// func (rsb *DefaultResponseBuilder) New() ResponseBuilder {
// return NewDefaultResponseBuilder()
// }
func (*DefaultResponseBuilder) mustEmbedDefaultResponseBuilder() {}
func NewDefaultResponseBuilder() *DefaultResponseBuilder {
return &DefaultResponseBuilder{}
}
func (rsb *DefaultResponseBuilder) SetStatus(code *int) *DefaultResponseBuilder {
rsb.status = code
return rsb
}
func (rsb *DefaultResponseBuilder) SetHeader(parsed *Header, fields header) *DefaultResponseBuilder {
rsb.header.Header = parsed
rsb.header.fields = fields
return rsb
}
func (rsb *DefaultResponseBuilder) SetBody(parsed *Body, fields body) *DefaultResponseBuilder {
rsb.body.Body = parsed
rsb.body.fields = fields
return rsb
}
func (rsb *DefaultResponseBuilder) SetDefaults() *DefaultResponseBuilder {
if rsb.status == nil {
c := http.StatusOK
rsb.status = &c
}
if rsb.header.Header == nil || rsb.header.fields == nil {
hd := Header{"Content-Type": []string{"text/plain", "charset=utf-8"}}
rsb.header.Header = &hd
hfd := struct{ Header }{Header: hd}
rsb.header.fields = &hfd
}
if rsb.body.Body == nil || rsb.body.fields == nil {
bd := make(Body, 0)
rsb.body.Body = &bd
bfd := struct{ Body }{Body: bd}
rsb.body.fields = &bfd
}
return rsb
}
func (rsb *DefaultResponseBuilder) Header(header map[string][]string) (e Error) {
*rsb.header.Header = header
err := rsb.header.Header.Unmarshal(rsb.header.fields)
if err != nil {
return rsb.errorHandler.Error(DefaultErrorInternalServerError)
}
return
}
func (rsb *DefaultResponseBuilder) Write(body []byte) (e Error) {
*rsb.body.Body = append(*rsb.body.Body, body...)
return
}
func (rsb *DefaultResponseBuilder) Response() (res *response) {
res = &response{
Status: *rsb.status,
Header: *rsb.header.Header,
Body: *rsb.body.Body,
}
return
}

View File

@ -8,17 +8,25 @@ import (
"somehole.com/common/log" "somehole.com/common/log"
) )
type Response struct { type response struct {
Status int Status int
Header Header Header Header
Body Body Body Body
} }
type Response[RSB ResponseBuilder] struct {
response
}
func NewResponse[RSB ResponseBuilder](rsb RSB) *Response[RSB] {
return &Response[RSB]{*rsb.Response()}
}
type Error interface { type Error interface {
Error(e Error) (err Error) Error(e Error) (err Error)
Status() (code int) Status() (code int)
String() (out string) String() (out string)
Response() (res *Response) Response() (res *response)
} }
type request struct { type request struct {
@ -46,12 +54,25 @@ type RequestBuilder interface {
New() (rqb RequestBuilder) New() (rqb RequestBuilder)
Allowed(method string) (err Error) Allowed(method string) (err Error)
Url(url url.URL) (err Error) Url(url url.URL) (err Error)
Header(header Header) (err Error) Header(map[string][]string) (err Error)
Values(values Values) (err Error) Values(map[string][]string) (err Error)
Body(body io.ReadCloser) (err Error) Body(body io.ReadCloser) (err Error)
Request() *request Request() *request
} }
func (*Response[RSB]) ResponseBuilder() ResponseBuilder {
var rsb RSB
return rsb.New()
}
type ResponseBuilder interface {
mustEmbedDefaultResponseBuilder()
New() (rsb ResponseBuilder)
Header(header Header) (err Error)
Write(body []byte) (err Error)
Response() *response
}
type writer struct { type writer struct {
http.ResponseWriter http.ResponseWriter
log.Logger log.Logger
@ -82,47 +103,47 @@ const (
numServeStages numServeStages
) )
type ServeFunc[RQB RequestBuilder] func(req *Request[RQB]) (res *Response, err Error) type ServeFunc[RQB RequestBuilder, RSB ResponseBuilder] func(req *Request[RQB]) (res *Response[RSB], err Error)
type server[RQB RequestBuilder] struct { type server[RQB RequestBuilder, RSB ResponseBuilder] struct {
logger log.Logger logger log.Logger
serve [numServeStages][]ServeFunc[RQB] serve [numServeStages][]ServeFunc[RQB, RSB]
} }
func NewServer[RQB RequestBuilder](serve func(req *Request[RQB]) (res *Response, err Error)) (srv *server[RQB]) { func NewServer[RQB RequestBuilder, RSB ResponseBuilder](serve ServeFunc[RQB, RSB]) (srv *server[RQB, RSB]) {
srv = &server[RQB]{ srv = &server[RQB, RSB]{
serve: [numServeStages][]ServeFunc[RQB]{}, serve: [numServeStages][]ServeFunc[RQB, RSB]{},
} }
srv.serve[serveMain] = append(srv.serve[serveMain], serve) srv.serve[serveMain] = append(srv.serve[serveMain], serve)
return srv return srv
} }
func (srv *server[RQB]) SetLogger(logger log.Logger) *server[RQB] { func (srv *server[RQB, RSB]) SetLogger(logger log.Logger) *server[RQB, RSB] {
srv.logger = logger srv.logger = logger
return srv return srv
} }
func (srv *server[RQB]) addServeFunc(when serveStage, serve ServeFunc[RQB]) *server[RQB] { func (srv *server[RQB, RSB]) addServeFunc(when serveStage, serve ServeFunc[RQB, RSB]) *server[RQB, RSB] {
if srv.serve[when] == nil { if srv.serve[when] == nil {
srv.serve[when] = make([]ServeFunc[RQB], 0) srv.serve[when] = make([]ServeFunc[RQB, RSB], 0)
} }
srv.serve[when] = append(srv.serve[when], serve) srv.serve[when] = append(srv.serve[when], serve)
return srv return srv
} }
func (srv *server[RQB]) PreServeFunc(serve ServeFunc[RQB]) *server[RQB] { func (srv *server[RQB, RSB]) PreServeFunc(serve ServeFunc[RQB, RSB]) *server[RQB, RSB] {
return srv.addServeFunc(servePre, serve) return srv.addServeFunc(servePre, serve)
} }
func (srv *server[RQB]) AddServeFunc(serve ServeFunc[RQB]) *server[RQB] { func (srv *server[RQB, RSB]) AddServeFunc(serve ServeFunc[RQB, RSB]) *server[RQB, RSB] {
return srv.addServeFunc(serveMain, serve) return srv.addServeFunc(serveMain, serve)
} }
func (srv *server[RQB]) PostServeFunc(serve ServeFunc[RQB]) *server[RQB] { func (srv *server[RQB, RSB]) PostServeFunc(serve ServeFunc[RQB, RSB]) *server[RQB, RSB] {
return srv.addServeFunc(servePost, serve) return srv.addServeFunc(servePost, serve)
} }
func (srv *server[RQB]) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (srv *server[RQB, RSB]) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var rqb RQB var rqb RQB
rqb = rqb.New().(RQB) rqb = rqb.New().(RQB)
wr := writer{ResponseWriter: w, Logger: srv.logger} wr := writer{ResponseWriter: w, Logger: srv.logger}
@ -132,14 +153,14 @@ func (srv *server[RQB]) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if ok := wr.handleError(rqb.Url(*r.URL)); !ok { if ok := wr.handleError(rqb.Url(*r.URL)); !ok {
return return
} }
if ok := wr.handleError(rqb.Header(Header(r.Header))); !ok { if ok := wr.handleError(rqb.Header(r.Header)); !ok {
return return
} }
if ok := wr.handleError(rqb.Body(r.Body)); !ok { if ok := wr.handleError(rqb.Body(r.Body)); !ok {
return return
} }
r.ParseForm() r.ParseForm()
if ok := wr.handleError(rqb.Values(Values(r.Form))); !ok { if ok := wr.handleError(rqb.Values(r.Form)); !ok {
return return
} }
for _, stage := range srv.serve { for _, stage := range srv.serve {
@ -151,7 +172,7 @@ func (srv *server[RQB]) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if res.Header != nil { if res.Header != nil {
for key, value := range res.Header { for key, value := range res.Header {
for _, v := range value { for _, v := range value {
w.Header().Add(key, v) wr.Header().Add(key, v)
} }
} }
} }