request/response: add more implementations

This commit is contained in:
Muyao CHEN 2024-09-25 22:45:25 +02:00
parent 099d1aeb0f
commit 8f4b378fdd

View File

@ -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
}
// }}}