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
}
func (e DefaultError) Response() *Response {
func (e DefaultError) Response() *response {
body, err := json.Marshal(struct{ Error string }{Error: e.String()})
if err != nil {
panic(err)
}
return &Response{
return &response{
Status: e.Status(),
Header: Header{"Content-Type": []string{"text/javascript", "charset=utf-8"}},
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)
// func (*DefaultRequestBuilder) New() RequestBuilder {
// return NewDefaultRequestBuilder()
@ -177,7 +177,7 @@ func (rqb *DefaultRequestBuilder) Url(url url.URL) (e Error) {
return
}
func (rqb *DefaultRequestBuilder) Header(header Header) (e Error) {
func (rqb *DefaultRequestBuilder) Header(header map[string][]string) (e Error) {
*rqb.header.Header = header
err := rqb.header.Header.Unmarshal(rqb.header.fields)
if err != nil {
@ -192,7 +192,7 @@ func (rqb *DefaultRequestBuilder) Body(body io.ReadCloser) (e Error) {
return
}
func (rqb *DefaultRequestBuilder) Values(values Values) (e Error) {
func (rqb *DefaultRequestBuilder) Values(values map[string][]string) (e Error) {
*rqb.values.Values = values
err := rqb.values.Values.Unmarshal(rqb.values.fields)
if err != nil {
@ -210,3 +210,88 @@ func (rqb *DefaultRequestBuilder) Request() (req *request) {
}
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"
)
type Response struct {
type response struct {
Status int
Header Header
Body Body
}
type Response[RSB ResponseBuilder] struct {
response
}
func NewResponse[RSB ResponseBuilder](rsb RSB) *Response[RSB] {
return &Response[RSB]{*rsb.Response()}
}
type Error interface {
Error(e Error) (err Error)
Status() (code int)
String() (out string)
Response() (res *Response)
Response() (res *response)
}
type request struct {
@ -46,12 +54,25 @@ type RequestBuilder interface {
New() (rqb RequestBuilder)
Allowed(method string) (err Error)
Url(url url.URL) (err Error)
Header(header Header) (err Error)
Values(values Values) (err Error)
Header(map[string][]string) (err Error)
Values(map[string][]string) (err Error)
Body(body io.ReadCloser) (err Error)
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 {
http.ResponseWriter
log.Logger
@ -82,47 +103,47 @@ const (
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
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]) {
srv = &server[RQB]{
serve: [numServeStages][]ServeFunc[RQB]{},
func NewServer[RQB RequestBuilder, RSB ResponseBuilder](serve ServeFunc[RQB, RSB]) (srv *server[RQB, RSB]) {
srv = &server[RQB, RSB]{
serve: [numServeStages][]ServeFunc[RQB, RSB]{},
}
srv.serve[serveMain] = append(srv.serve[serveMain], serve)
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
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 {
srv.serve[when] = make([]ServeFunc[RQB], 0)
srv.serve[when] = make([]ServeFunc[RQB, RSB], 0)
}
srv.serve[when] = append(srv.serve[when], serve)
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)
}
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)
}
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)
}
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
rqb = rqb.New().(RQB)
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 {
return
}
if ok := wr.handleError(rqb.Header(Header(r.Header))); !ok {
if ok := wr.handleError(rqb.Header(r.Header)); !ok {
return
}
if ok := wr.handleError(rqb.Body(r.Body)); !ok {
return
}
r.ParseForm()
if ok := wr.handleError(rqb.Values(Values(r.Form))); !ok {
if ok := wr.handleError(rqb.Values(r.Form)); !ok {
return
}
for _, stage := range srv.serve {
@ -151,7 +172,7 @@ func (srv *server[RQB]) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if res.Header != nil {
for key, value := range res.Header {
for _, v := range value {
w.Header().Add(key, v)
wr.Header().Add(key, v)
}
}
}