293 lines
5.7 KiB
Go
Raw Normal View History

2024-01-12 19:18:33 +08:00
package nf
import (
"bytes"
"encoding/json"
2024-01-12 21:42:29 +08:00
"fmt"
2024-01-12 19:18:33 +08:00
"io"
2024-01-12 21:42:29 +08:00
"mime/multipart"
"net"
2024-01-12 19:18:33 +08:00
"net/http"
"strings"
)
type Ctx struct {
2024-02-20 15:34:00 +08:00
writermem responseWriter
2024-01-12 19:18:33 +08:00
// origin objects
2024-01-14 19:10:05 +08:00
writer http.ResponseWriter
2024-01-12 19:18:33 +08:00
Request *http.Request
// request info
path string
2024-02-20 15:34:00 +08:00
method string
2024-01-12 19:18:33 +08:00
// response info
StatusCode int
2024-02-20 15:34:00 +08:00
app *App
params *Params
index int
handlers []HandlerFunc
locals map[string]interface{}
skippedNodes *[]skippedNode
fullPath string
Params Params
2024-01-12 19:18:33 +08:00
}
func newContext(app *App, writer http.ResponseWriter, request *http.Request) *Ctx {
2024-02-20 15:34:00 +08:00
skippedNodes := make([]skippedNode, 0, app.maxSections)
v := make(Params, 0, app.maxParams)
ctx := &Ctx{
2024-01-14 19:10:05 +08:00
writer: writer,
2024-02-20 15:34:00 +08:00
writermem: responseWriter{},
2024-01-14 19:10:05 +08:00
Request: request,
path: request.URL.Path,
2024-02-20 15:34:00 +08:00
method: request.Method,
2024-01-14 19:10:05 +08:00
StatusCode: 200,
2024-01-12 19:18:33 +08:00
2024-02-20 15:34:00 +08:00
app: app,
index: -1,
locals: map[string]interface{}{},
handlers: make([]HandlerFunc, 0),
skippedNodes: &skippedNodes,
params: &v,
}
ctx.writermem = responseWriter{
ResponseWriter: ctx.writer,
size: -1,
status: 0,
2024-01-12 19:18:33 +08:00
}
2024-02-20 15:34:00 +08:00
return ctx
2024-01-12 19:18:33 +08:00
}
2024-01-13 20:44:20 +08:00
func (c *Ctx) Locals(key string, value ...interface{}) interface{} {
2024-01-12 19:18:33 +08:00
data := c.locals[key]
if len(value) > 0 {
c.locals[key] = value[0]
}
return data
}
2024-02-20 15:34:00 +08:00
func (c *Ctx) Method(overWrite ...string) string {
method := c.Request.Method
if len(overWrite) > 0 && overWrite[0] != "" {
c.Request.Method = overWrite[0]
}
return method
}
2024-01-12 19:18:33 +08:00
func (c *Ctx) Path(overWrite ...string) string {
path := c.Request.URL.Path
if len(overWrite) > 0 && overWrite[0] != "" {
c.Request.URL.Path = overWrite[0]
}
return path
}
2024-01-29 19:16:36 +08:00
func (c *Ctx) Cookies(key string, defaultValue ...string) string {
var (
dv = ""
)
if len(defaultValue) > 0 {
dv = defaultValue[0]
}
cookie, err := c.Request.Cookie(key)
if err != nil || cookie.Value == "" {
return dv
}
return cookie.Value
}
2024-01-12 19:18:33 +08:00
func (c *Ctx) Next() error {
c.index++
2024-02-27 16:19:19 +08:00
if c.index >= len(c.handlers) {
return nil
}
2024-02-20 16:04:44 +08:00
var (
err error
handler = c.handlers[c.index]
)
2024-02-20 16:04:44 +08:00
if handler != nil {
if err = handler(c); err != nil {
return err
2024-02-20 15:34:00 +08:00
}
2024-01-12 19:18:33 +08:00
}
2024-02-20 16:04:44 +08:00
c.index++
2024-02-20 15:34:00 +08:00
return nil
2024-01-12 19:18:33 +08:00
}
/* ===============================================================
|| Handle Ctx Request Part
=============================================================== */
func (c *Ctx) verify() error {
// 验证 body size
if c.app.config.BodyLimit != -1 && c.Request.ContentLength > c.app.config.BodyLimit {
return NewNFError(413, "Content Too Large")
}
return nil
}
func (c *Ctx) Param(key string) string {
2024-02-20 15:34:00 +08:00
return c.Params.ByName(key)
2024-01-12 19:18:33 +08:00
}
func (c *Ctx) Form(key string) string {
return c.Request.FormValue(key)
2024-02-27 16:19:19 +08:00
}
// FormValue fiber ctx function
func (c *Ctx) FormValue(key string) string {
return c.Request.FormValue(key)
2024-01-12 19:18:33 +08:00
}
2024-01-12 21:42:29 +08:00
func (c *Ctx) FormFile(key string) (*multipart.FileHeader, error) {
_, fh, err := c.Request.FormFile(key)
return fh, err
}
2024-01-12 19:18:33 +08:00
func (c *Ctx) Query(key string) string {
return c.Request.URL.Query().Get(key)
}
func (c *Ctx) Get(key string, defaultValue ...string) string {
value := c.Request.Header.Get(key)
if value == "" && len(defaultValue) > 0 {
return defaultValue[0]
}
return value
}
2024-01-12 21:42:29 +08:00
func (c *Ctx) IP() string {
ip, _, err := net.SplitHostPort(strings.TrimSpace(c.Request.RemoteAddr))
if err != nil {
return ""
}
return ip
}
2024-01-12 19:18:33 +08:00
func (c *Ctx) BodyParser(out interface{}) error {
var (
err error
ctype = strings.ToLower(c.Request.Header.Get("Content-Type"))
)
ctype = parseVendorSpecificContentType(ctype)
ctypeEnd := strings.IndexByte(ctype, ';')
if ctypeEnd != -1 {
ctype = ctype[:ctypeEnd]
}
if strings.HasSuffix(ctype, "json") {
bs, err := io.ReadAll(c.Request.Body)
if err != nil {
return err
}
2024-02-01 18:06:07 +08:00
_ = c.Request.Body.Close()
2024-01-12 19:18:33 +08:00
c.Request.Body = io.NopCloser(bytes.NewReader(bs))
return json.Unmarshal(bs, out)
}
if strings.HasPrefix(ctype, MIMEApplicationForm) {
if err = c.Request.ParseForm(); err != nil {
return NewNFError(400, err.Error())
}
return parseToStruct("form", out, c.Request.Form)
}
if strings.HasPrefix(ctype, MIMEMultipartForm) {
if err = c.Request.ParseMultipartForm(c.app.config.BodyLimit); err != nil {
return NewNFError(400, err.Error())
}
return parseToStruct("form", out, c.Request.PostForm)
}
return NewNFError(422, "Unprocessable Content")
}
func (c *Ctx) QueryParser(out interface{}) error {
2024-01-12 21:42:29 +08:00
//v := reflect.ValueOf(out)
//
//if v.Kind() == reflect.Ptr && v.Elem().Kind() != reflect.Map {
//}
2024-01-12 19:18:33 +08:00
return parseToStruct("query", out, c.Request.URL.Query())
}
2024-01-12 21:42:29 +08:00
/* ===============================================================
|| Handle Ctx Response Part
=============================================================== */
func (c *Ctx) Status(code int) *Ctx {
2024-02-20 15:34:00 +08:00
c.writermem.WriteHeader(code)
c.StatusCode = c.writermem.status
2024-01-12 21:42:29 +08:00
return c
}
func (c *Ctx) Set(key string, value string) {
2024-02-20 15:34:00 +08:00
c.writermem.Header().Set(key, value)
2024-01-12 21:42:29 +08:00
}
func (c *Ctx) SetHeader(key string, value string) {
2024-02-20 15:34:00 +08:00
c.writermem.Header().Set(key, value)
2024-01-12 21:42:29 +08:00
}
func (c *Ctx) SendString(data string) error {
c.SetHeader("Content-Type", "text/plain")
_, err := c.Write([]byte(data))
return err
}
func (c *Ctx) Writef(format string, values ...interface{}) (int, error) {
c.SetHeader("Content-Type", "text/plain")
2024-01-14 19:10:05 +08:00
return c.writer.Write([]byte(fmt.Sprintf(format, values...)))
2024-01-12 21:42:29 +08:00
}
func (c *Ctx) JSON(data interface{}) error {
2024-01-19 20:15:36 +08:00
c.SetHeader("Content-Type", MIMEApplicationJSON)
2024-01-12 21:42:29 +08:00
2024-02-20 15:34:00 +08:00
encoder := json.NewEncoder(&c.writermem)
2024-01-12 21:42:29 +08:00
if err := encoder.Encode(data); err != nil {
return err
}
return nil
}
2024-01-14 19:10:05 +08:00
func (c *Ctx) RawWriter() http.ResponseWriter {
return c.writer
}
2024-01-12 21:42:29 +08:00
func (c *Ctx) Write(data []byte) (int, error) {
2024-02-20 15:34:00 +08:00
return c.writermem.Write(data)
2024-01-12 21:42:29 +08:00
}
func (c *Ctx) HTML(html string) error {
c.SetHeader("Content-Type", "text/html")
2024-01-14 19:10:05 +08:00
_, err := c.writer.Write([]byte(html))
2024-01-12 21:42:29 +08:00
return err
}