sync from project

This commit is contained in:
2025-06-18 10:12:19 +08:00
parent 61ffeeb3b8
commit fb579e8689
20 changed files with 1332 additions and 103 deletions

View File

@ -12,10 +12,13 @@ import (
"git.jeffthecoder.xyz/public/lazyhandler/util"
)
type ErrArgumentIsNotExtractable int
type ErrArgumentIsNotExtractable struct {
Index int
Type reflect.Type
}
func (err ErrArgumentIsNotExtractable) Error() string {
return fmt.Sprintf("argument %v is not extractable", int(err))
return fmt.Sprintf("argument %v is not extractable: %s", err.Index, err.Type.String())
}
type ErrReturnValueNotConvertableIntoResponsePart int
@ -27,6 +30,7 @@ func (err ErrReturnValueNotConvertableIntoResponsePart) Error() string {
var (
ErrNotAFunc = errors.New("not a function")
ErrDuplicateResponseWriterExtractor = errors.New("duplicate response writer extractor")
ErrDuplicateRequestBodyExtractor = errors.New("duplicate request body extractor")
ErrResponseWriterCannotBeExtracted = errors.New("http.ResponseWriter extractor must not exists if function has return value")
)
@ -50,6 +54,7 @@ func MagicHandler(fn any) (http.Handler, error) {
}
responseWriterExtracted := -1
requestBodyExtracted := -1
extractors := make([]func(http.ResponseWriter, *http.Request) (any, error), t.NumIn())
for idx := 0; idx < t.NumIn(); idx++ {
@ -57,7 +62,10 @@ func MagicHandler(fn any) (http.Handler, error) {
extractor, isTakeResponseWriter := magic.GetExtractor(in)
if extractor == nil {
return nil, ErrArgumentIsNotExtractable(idx)
return nil, ErrArgumentIsNotExtractable{
Index: idx,
Type: in,
}
}
if isTakeResponseWriter {
if responseWriterExtracted >= 0 {
@ -65,6 +73,14 @@ func MagicHandler(fn any) (http.Handler, error) {
}
responseWriterExtracted = idx
}
if magic.IsTakeBody(in) {
if requestBodyExtracted >= 0 {
return nil, ErrDuplicateRequestBodyExtractor
}
requestBodyExtracted = idx
}
extractors[idx] = extractor
}
@ -98,6 +114,14 @@ func MagicHandler(fn any) (http.Handler, error) {
if _, ok := util.Implements[magic.RespondWriter](out); ok {
continue
}
if _, ok := util.Implements[magic.RespondWriter](reflect.PointerTo(out)); ok {
continue
}
if out.Kind() == reflect.Pointer {
if _, ok := util.Implements[magic.RespondWriter](out.Elem()); ok {
continue
}
}
// last is error
if _, ok := util.Implements[error](out); ok && idx == t.NumOut()-1 {
@ -108,12 +132,6 @@ func MagicHandler(fn any) (http.Handler, error) {
}
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var closers []io.Closer
defer func() {
for _, closer := range closers {
closer.Close()
}
}()
in := make([]reflect.Value, len(extractors))
for idx, extractor := range extractors {
v, err := extractor(w, r)
@ -128,9 +146,6 @@ func MagicHandler(fn any) (http.Handler, error) {
}
return
}
if closer, ok := v.(io.Closer); ok {
defer closer.Close()
}
in[idx] = reflect.ValueOf(v)
}
values := funcValue.Call(in)
@ -169,6 +184,11 @@ func MagicHandler(fn any) (http.Handler, error) {
continue
}
responseWriter.WriteResponse(w)
} else if responseWriter, ok := util.Implements[magic.RespondWriter](&value); ok {
if responseWriter == nil {
continue
}
responseWriter.WriteResponse(w)
} else if headers, ok := obj.(http.Header); ok { // not
for name, values := range headers {
for idx, value := range values {