2024-10-07 21:39:42 +00:00
|
|
|
package router
|
|
|
|
|
|
|
|
import (
|
2024-10-10 18:26:07 +00:00
|
|
|
"io"
|
2024-10-07 21:39:42 +00:00
|
|
|
"net/http"
|
2024-10-10 18:26:07 +00:00
|
|
|
"net/url"
|
2024-10-07 21:39:42 +00:00
|
|
|
|
|
|
|
"somehole.com/common/log"
|
|
|
|
)
|
|
|
|
|
2024-10-10 18:26:07 +00:00
|
|
|
type Response struct {
|
|
|
|
Status int
|
|
|
|
Header Header
|
|
|
|
Body Body
|
|
|
|
}
|
|
|
|
|
|
|
|
type Error interface {
|
|
|
|
Error(e Error) (err Error)
|
|
|
|
Status() (code int)
|
|
|
|
String() (out string)
|
|
|
|
Response() (res *Response)
|
|
|
|
}
|
|
|
|
|
|
|
|
type request struct {
|
|
|
|
Url url.URL
|
|
|
|
Header Header
|
|
|
|
Values Values
|
|
|
|
Body Body
|
|
|
|
}
|
|
|
|
|
|
|
|
type Request[RQB RequestBuilder] struct {
|
|
|
|
request
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewRequest[RQB RequestBuilder](rqb RQB) *Request[RQB] {
|
|
|
|
return &Request[RQB]{*rqb.Request()}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*Request[RQB]) RequestBuilder() RequestBuilder {
|
|
|
|
var rqb RQB
|
|
|
|
return rqb.New()
|
|
|
|
}
|
|
|
|
|
|
|
|
type RequestBuilder interface {
|
|
|
|
mustEmbedDefaultRequestBuilder()
|
|
|
|
New() (rqb RequestBuilder)
|
|
|
|
Allowed(method string) (err Error)
|
|
|
|
Url(url url.URL) (err Error)
|
|
|
|
Header(header Header) (err Error)
|
|
|
|
Values(values Values) (err Error)
|
|
|
|
Body(body io.ReadCloser) (err Error)
|
|
|
|
Request() *request
|
|
|
|
}
|
|
|
|
|
|
|
|
type writer struct {
|
|
|
|
http.ResponseWriter
|
|
|
|
log.Logger
|
|
|
|
}
|
|
|
|
|
|
|
|
func (w *writer) handleError(err Error) (ok bool) {
|
|
|
|
if err != nil {
|
|
|
|
res := err.Response()
|
|
|
|
for key, value := range res.Header {
|
|
|
|
for _, v := range value {
|
|
|
|
w.Header().Add(key, v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
w.WriteHeader(res.Status)
|
|
|
|
w.Write(res.Body)
|
|
|
|
w.Logf(log.LevelError, err.String())
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
type serveStage uint8
|
2024-10-07 21:39:42 +00:00
|
|
|
|
|
|
|
const (
|
2024-10-10 18:26:07 +00:00
|
|
|
servePre serveStage = iota
|
|
|
|
serveMain
|
|
|
|
servePost
|
|
|
|
numServeStages
|
2024-10-07 21:39:42 +00:00
|
|
|
)
|
|
|
|
|
2024-10-10 18:26:07 +00:00
|
|
|
type ServeFunc[RQB RequestBuilder] func(req *Request[RQB]) (res *Response, err Error)
|
|
|
|
|
|
|
|
type server[RQB RequestBuilder] struct {
|
|
|
|
logger log.Logger
|
|
|
|
serve [numServeStages][]ServeFunc[RQB]
|
|
|
|
}
|
|
|
|
|
2024-10-10 18:38:05 +00:00
|
|
|
func NewServer[RQB RequestBuilder](serve func(req *Request[RQB]) (res *Response, err Error)) (srv *server[RQB]) {
|
2024-10-10 18:26:07 +00:00
|
|
|
srv = &server[RQB]{
|
|
|
|
serve: [numServeStages][]ServeFunc[RQB]{},
|
2024-10-07 21:39:42 +00:00
|
|
|
}
|
2024-10-10 18:26:07 +00:00
|
|
|
srv.serve[serveMain] = append(srv.serve[serveMain], serve)
|
2024-10-07 21:39:42 +00:00
|
|
|
return srv
|
|
|
|
}
|
|
|
|
|
2024-10-10 18:26:07 +00:00
|
|
|
func (srv *server[RQB]) SetLogger(logger log.Logger) *server[RQB] {
|
2024-10-09 15:40:28 +00:00
|
|
|
srv.logger = logger
|
|
|
|
return srv
|
|
|
|
}
|
|
|
|
|
2024-10-10 18:26:07 +00:00
|
|
|
func (srv *server[RQB]) addServeFunc(when serveStage, serve ServeFunc[RQB]) *server[RQB] {
|
2024-10-07 21:39:42 +00:00
|
|
|
if srv.serve[when] == nil {
|
2024-10-10 18:26:07 +00:00
|
|
|
srv.serve[when] = make([]ServeFunc[RQB], 0)
|
2024-10-07 21:39:42 +00:00
|
|
|
}
|
|
|
|
srv.serve[when] = append(srv.serve[when], serve)
|
|
|
|
return srv
|
|
|
|
}
|
|
|
|
|
2024-10-10 18:26:07 +00:00
|
|
|
func (srv *server[RQB]) PreServeFunc(serve ServeFunc[RQB]) *server[RQB] {
|
|
|
|
return srv.addServeFunc(servePre, serve)
|
2024-10-07 21:39:42 +00:00
|
|
|
}
|
|
|
|
|
2024-10-10 18:26:07 +00:00
|
|
|
func (srv *server[RQB]) AddServeFunc(serve ServeFunc[RQB]) *server[RQB] {
|
|
|
|
return srv.addServeFunc(serveMain, serve)
|
2024-10-07 21:39:42 +00:00
|
|
|
}
|
|
|
|
|
2024-10-10 18:26:07 +00:00
|
|
|
func (srv *server[RQB]) PostServeFunc(serve ServeFunc[RQB]) *server[RQB] {
|
|
|
|
return srv.addServeFunc(servePost, serve)
|
2024-10-07 21:39:42 +00:00
|
|
|
}
|
|
|
|
|
2024-10-10 18:26:07 +00:00
|
|
|
func (srv *server[RQB]) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
|
|
var rqb RQB
|
|
|
|
rqb = rqb.New().(RQB)
|
|
|
|
wr := writer{ResponseWriter: w, Logger: srv.logger}
|
|
|
|
if ok := wr.handleError(rqb.Allowed(r.Method)); !ok {
|
2024-10-07 21:39:42 +00:00
|
|
|
return
|
|
|
|
}
|
2024-10-10 18:26:07 +00:00
|
|
|
if ok := wr.handleError(rqb.Url(*r.URL)); !ok {
|
2024-10-09 21:09:12 +00:00
|
|
|
return
|
|
|
|
}
|
2024-10-10 18:26:07 +00:00
|
|
|
if ok := wr.handleError(rqb.Header(Header(r.Header))); !ok {
|
2024-10-08 21:57:25 +00:00
|
|
|
return
|
|
|
|
}
|
2024-10-10 18:26:07 +00:00
|
|
|
if ok := wr.handleError(rqb.Body(r.Body)); !ok {
|
2024-10-07 21:39:42 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
r.ParseForm()
|
2024-10-10 18:26:07 +00:00
|
|
|
if ok := wr.handleError(rqb.Values(Values(r.Form))); !ok {
|
2024-10-07 21:39:42 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
for _, stage := range srv.serve {
|
|
|
|
for _, s := range stage {
|
2024-10-10 18:26:07 +00:00
|
|
|
res, err := s(NewRequest(rqb))
|
|
|
|
if ok := wr.handleError(err); !ok {
|
2024-10-07 21:39:42 +00:00
|
|
|
return
|
|
|
|
}
|
2024-10-10 18:26:07 +00:00
|
|
|
if res.Header != nil {
|
|
|
|
for key, value := range res.Header {
|
2024-10-07 21:39:42 +00:00
|
|
|
for _, v := range value {
|
|
|
|
w.Header().Add(key, v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-10-10 18:26:07 +00:00
|
|
|
if len(res.Body) > 0 {
|
|
|
|
wr.Write(res.Body)
|
|
|
|
}
|
2024-10-07 21:39:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|