diff --git a/framework/request.go b/framework/request.go index 17054fb..e38bb7d 100644 --- a/framework/request.go +++ b/framework/request.go @@ -1,6 +1,11 @@ package framework import ( + "bytes" + "encoding/json" + "encoding/xml" + "errors" + "io" "mime/multipart" "net/url" @@ -281,3 +286,126 @@ func (ctx *Context) FormStringSlice(key string, defval []string) ([]string, bool } // }}} +// {{{ type binder + +var ( + ErrNoRequest = errors.New("missing request in the context") + ErrNotSingleObj = errors.New("body must have only a single value") +) + +// JSON body +func (ctx *Context) BindJSON(obj any) error { + if ctx.request == nil { + return ErrNoRequest + } + dec := json.NewDecoder(ctx.request.Body) + err := dec.Decode(obj) + if err != nil { + return err + } + err = dec.Decode(&struct{}{}) + if err != io.EOF { + return ErrNotSingleObj + } + + return nil +} + +// XML body +func (ctx *Context) BindXML(obj any) error { + if ctx.request == nil { + return ErrNoRequest + } + dec := xml.NewDecoder(ctx.request.Body) + err := dec.Decode(obj) + if err != nil { + return err + } + err = dec.Decode(&struct{}{}) + if err != io.EOF { + return ErrNotSingleObj + } + + return nil +} + +// RAW body +func (ctx *Context) GetRawData() ([]byte, error) { + if ctx.request == nil { + return []byte{}, ErrNoRequest + } + body, err := io.ReadAll(ctx.request.Body) + if err != nil { + return []byte{}, err + } + /* Restore the body (io.ReadCloser) to it's original state */ + ctx.request.Body = io.NopCloser(bytes.NewBuffer(body)) + + return body, nil +} + +// }}} +// {{{ Basic informations + +func (ctx *Context) Uri() string { + return ctx.request.RequestURI +} + +func (ctx *Context) Method() string { + return ctx.request.Method +} + +func (ctx *Context) Host() string { + return ctx.request.Host +} + +func (ctx *Context) ClientIP() string { + r := ctx.request + ipAddress := r.Header.Get("X-Real-Ip") + if ipAddress == "" { + ipAddress = r.Header.Get("X-Forwarded-For") + } + if ipAddress == "" { + ipAddress = r.RemoteAddr + } + return ipAddress +} + +// }}} +// {{{ Headers + +// Header +func (ctx *Context) Headers() map[string][]string { + return ctx.request.Header +} + +func (ctx *Context) Header(key string) (string, bool) { + vals := ctx.request.Header.Values(key) + if vals == nil || len(vals) <= 0 { + return "", false + } + return vals[0], true +} + +// }}} +// {{{ Cookies + +// Cookies gets cookie key-value pairs +func (ctx *Context) Cookies() map[string]string { + cookies := ctx.request.Cookies() + ret := map[string]string{} + for _, c := range cookies { + ret[c.Name] = c.Value + } + return ret +} + +func (ctx *Context) Cookie(key string) (string, bool) { + cookies := ctx.Cookies() + if val, ok := cookies[key]; ok { + return val, true + } + return "", false +} + +// }}}