2017-08-04 08:20:59 +00:00
|
|
|
|
package hotime
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
2026-01-22 04:59:53 +08:00
|
|
|
|
"bytes"
|
2017-08-04 08:20:59 +00:00
|
|
|
|
"encoding/json"
|
2026-01-22 04:59:53 +08:00
|
|
|
|
"io"
|
|
|
|
|
|
"mime/multipart"
|
2017-08-04 08:20:59 +00:00
|
|
|
|
"net/http"
|
2022-08-20 22:38:15 +08:00
|
|
|
|
"strings"
|
2026-01-22 04:59:53 +08:00
|
|
|
|
"sync"
|
2022-03-26 16:53:40 +08:00
|
|
|
|
"time"
|
2026-01-22 04:59:53 +08:00
|
|
|
|
|
|
|
|
|
|
. "code.hoteas.com/golang/hotime/common"
|
|
|
|
|
|
. "code.hoteas.com/golang/hotime/db"
|
2017-08-04 08:20:59 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
type Context struct {
|
2021-05-25 05:08:17 +08:00
|
|
|
|
*Application
|
2017-08-04 08:20:59 +00:00
|
|
|
|
Resp http.ResponseWriter
|
|
|
|
|
|
Req *http.Request
|
2022-05-13 09:30:09 +08:00
|
|
|
|
Log Map //日志有则创建
|
2017-08-04 08:20:59 +00:00
|
|
|
|
RouterString []string
|
|
|
|
|
|
Config Map
|
|
|
|
|
|
Db *HoTimeDB
|
2020-02-20 14:20:56 +08:00
|
|
|
|
RespData Map
|
2022-05-13 09:30:09 +08:00
|
|
|
|
RespFunc func()
|
2022-08-08 02:37:15 +08:00
|
|
|
|
//CacheIns
|
2017-08-04 08:20:59 +00:00
|
|
|
|
SessionIns
|
2021-11-08 06:49:34 +08:00
|
|
|
|
DataSize int
|
2017-08-22 08:24:55 +00:00
|
|
|
|
HandlerStr string //复写请求url
|
2026-01-22 04:59:53 +08:00
|
|
|
|
|
|
|
|
|
|
// 请求参数缓存
|
|
|
|
|
|
reqJsonCache Map // JSON Body 缓存
|
|
|
|
|
|
reqMu sync.Once // 确保 JSON 只解析一次
|
2017-08-04 08:20:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-05-25 05:08:17 +08:00
|
|
|
|
// Mtd 唯一标志
|
|
|
|
|
|
func (that *Context) Mtd(router [3]string) Map {
|
|
|
|
|
|
that.Application.Router[router[0]][router[1]][router[2]](that)
|
|
|
|
|
|
d := that.RespData
|
|
|
|
|
|
that.RespData = nil
|
2017-08-04 08:20:59 +00:00
|
|
|
|
return d
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-22 02:44:53 +08:00
|
|
|
|
// 打印
|
2021-05-25 05:08:17 +08:00
|
|
|
|
func (that *Context) Display(statu int, data interface{}) {
|
2017-08-04 08:20:59 +00:00
|
|
|
|
|
2021-06-11 08:06:44 +08:00
|
|
|
|
resp := Map{"status": statu}
|
2017-08-04 08:20:59 +00:00
|
|
|
|
if statu != 0 {
|
|
|
|
|
|
temp := Map{}
|
2017-08-10 10:14:56 +00:00
|
|
|
|
|
2021-05-25 05:08:17 +08:00
|
|
|
|
tpe := that.Config.GetMap("error").GetString(ObjToStr(statu))
|
2017-08-22 08:24:55 +00:00
|
|
|
|
if tpe == "" {
|
2021-05-24 07:27:41 +08:00
|
|
|
|
//logFmt(errors.New("找不到对应的错误码"), 2, LOG_WARN)
|
2017-08-10 10:14:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
temp["type"] = tpe
|
2017-08-04 08:20:59 +00:00
|
|
|
|
temp["msg"] = data
|
|
|
|
|
|
resp["result"] = temp
|
2021-06-04 02:57:56 +08:00
|
|
|
|
//兼容android等需要json转对象的服务
|
|
|
|
|
|
resp["error"] = temp
|
2017-08-04 08:20:59 +00:00
|
|
|
|
} else {
|
|
|
|
|
|
resp["result"] = data
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2021-05-25 05:08:17 +08:00
|
|
|
|
that.RespData = resp
|
2017-08-04 08:20:59 +00:00
|
|
|
|
|
2021-05-25 05:08:17 +08:00
|
|
|
|
//that.Data=d;
|
2017-08-04 08:20:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-05-25 05:08:17 +08:00
|
|
|
|
func (that *Context) View() {
|
2022-05-13 09:30:09 +08:00
|
|
|
|
if that.RespFunc != nil {
|
2022-03-26 16:53:40 +08:00
|
|
|
|
that.RespFunc()
|
|
|
|
|
|
}
|
2021-05-25 05:08:17 +08:00
|
|
|
|
if that.RespData == nil {
|
2017-08-04 08:20:59 +00:00
|
|
|
|
return
|
|
|
|
|
|
}
|
2022-03-26 16:53:40 +08:00
|
|
|
|
//创建日志
|
2022-05-13 09:30:09 +08:00
|
|
|
|
if that.Log != nil {
|
2022-07-26 17:37:17 +08:00
|
|
|
|
that.Log["time"] = time.Now().Format("2006-01-02 15:04")
|
2022-05-13 09:30:09 +08:00
|
|
|
|
if that.Session("admin_id").Data != nil {
|
|
|
|
|
|
that.Log["admin_id"] = that.Session("admin_id").ToCeilInt()
|
2022-03-26 16:53:40 +08:00
|
|
|
|
}
|
2022-05-13 09:30:09 +08:00
|
|
|
|
if that.Session("user_id").Data != nil {
|
|
|
|
|
|
that.Log["user_id"] = that.Session("user_id").ToCeilInt()
|
2022-03-26 16:53:40 +08:00
|
|
|
|
}
|
2022-08-20 22:38:15 +08:00
|
|
|
|
//负载均衡优化
|
2022-09-02 00:04:23 +08:00
|
|
|
|
ipStr := ""
|
|
|
|
|
|
if that.Req.Header.Get("X-Forwarded-For") != "" {
|
|
|
|
|
|
ipStr = that.Req.Header.Get("X-Forwarded-For")
|
|
|
|
|
|
} else if that.Req.Header.Get("X-Real-IP") != "" {
|
|
|
|
|
|
ipStr = that.Req.Header.Get("X-Real-IP")
|
|
|
|
|
|
}
|
|
|
|
|
|
//负载均衡优化
|
|
|
|
|
|
if ipStr == "" {
|
|
|
|
|
|
//RemoteAddr := that.Req.RemoteAddr
|
|
|
|
|
|
ipStr = Substr(that.Req.RemoteAddr, 0, strings.Index(that.Req.RemoteAddr, ":"))
|
2022-08-20 22:38:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
that.Log["ip"] = ipStr
|
2022-05-13 09:30:09 +08:00
|
|
|
|
that.Db.Insert("logs", that.Log)
|
2022-03-26 16:53:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-05-25 05:08:17 +08:00
|
|
|
|
d, err := json.Marshal(that.RespData)
|
2017-08-04 08:20:59 +00:00
|
|
|
|
if err != nil {
|
2022-05-13 09:30:09 +08:00
|
|
|
|
that.Display(1, err.Error())
|
|
|
|
|
|
that.View()
|
2017-08-04 08:20:59 +00:00
|
|
|
|
return
|
|
|
|
|
|
}
|
2021-11-08 06:49:34 +08:00
|
|
|
|
that.DataSize = len(d)
|
2021-05-25 05:08:17 +08:00
|
|
|
|
that.RespData = nil
|
|
|
|
|
|
that.Resp.Write(d)
|
2026-01-22 04:59:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ==================== 请求参数获取方法 ====================
|
|
|
|
|
|
|
|
|
|
|
|
// ReqParam 获取 URL 查询参数,返回 *Obj 支持链式调用
|
|
|
|
|
|
// 用法: that.ReqParam("id").ToInt()
|
|
|
|
|
|
func (that *Context) ReqParam(key string) *Obj {
|
|
|
|
|
|
v := that.Req.URL.Query().Get(key)
|
|
|
|
|
|
if v == "" {
|
|
|
|
|
|
return &Obj{Data: nil}
|
|
|
|
|
|
}
|
|
|
|
|
|
return &Obj{Data: v}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ReqForm 获取表单参数,返回 *Obj 支持链式调用
|
|
|
|
|
|
// 用法: that.ReqForm("name").ToStr()
|
|
|
|
|
|
func (that *Context) ReqForm(key string) *Obj {
|
|
|
|
|
|
v := that.Req.FormValue(key)
|
|
|
|
|
|
if v == "" {
|
|
|
|
|
|
return &Obj{Data: nil}
|
|
|
|
|
|
}
|
|
|
|
|
|
return &Obj{Data: v}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ReqJson 获取 JSON Body 中的字段,返回 *Obj 支持链式调用
|
|
|
|
|
|
// 用法: that.ReqJson("data").ToMap()
|
|
|
|
|
|
func (that *Context) ReqJson(key string) *Obj {
|
|
|
|
|
|
that.parseJsonBody()
|
|
|
|
|
|
if that.reqJsonCache == nil {
|
|
|
|
|
|
return &Obj{Data: nil}
|
|
|
|
|
|
}
|
|
|
|
|
|
return &Obj{Data: that.reqJsonCache.Get(key)}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// parseJsonBody 解析 JSON Body(只解析一次,并发安全)
|
|
|
|
|
|
func (that *Context) parseJsonBody() {
|
|
|
|
|
|
that.reqMu.Do(func() {
|
|
|
|
|
|
if that.Req.Body == nil {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
body, err := io.ReadAll(that.Req.Body)
|
|
|
|
|
|
if err != nil || len(body) == 0 {
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
// 恢复 Body 以便后续代码可以再次读取
|
|
|
|
|
|
that.Req.Body = io.NopCloser(bytes.NewBuffer(body))
|
|
|
|
|
|
that.reqJsonCache = ObjToMap(string(body))
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ReqData 统一获取请求参数,优先级: JSON > Form > URL
|
|
|
|
|
|
// 用法: that.ReqData("id").ToInt()
|
|
|
|
|
|
func (that *Context) ReqData(key string) *Obj {
|
|
|
|
|
|
// 1. 优先从 JSON Body 获取
|
|
|
|
|
|
that.parseJsonBody()
|
|
|
|
|
|
if that.reqJsonCache != nil {
|
|
|
|
|
|
if v := that.reqJsonCache.Get(key); v != nil {
|
|
|
|
|
|
return &Obj{Data: v}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
// 2. 其次从 Form 获取
|
|
|
|
|
|
if v := that.Req.FormValue(key); v != "" {
|
|
|
|
|
|
return &Obj{Data: v}
|
|
|
|
|
|
}
|
|
|
|
|
|
// 3. 最后从 URL 参数获取
|
|
|
|
|
|
if v := that.Req.URL.Query().Get(key); v != "" {
|
|
|
|
|
|
return &Obj{Data: v}
|
|
|
|
|
|
}
|
|
|
|
|
|
return &Obj{Data: nil}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ReqFile 获取单个上传文件
|
|
|
|
|
|
// 用法: file, header, err := that.ReqFile("avatar")
|
|
|
|
|
|
func (that *Context) ReqFile(name string) (multipart.File, *multipart.FileHeader, error) {
|
|
|
|
|
|
return that.Req.FormFile(name)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ReqFiles 获取多个同名上传文件(批量上传场景)
|
|
|
|
|
|
// 用法: files, err := that.ReqFiles("images")
|
|
|
|
|
|
func (that *Context) ReqFiles(name string) ([]*multipart.FileHeader, error) {
|
|
|
|
|
|
if that.Req.MultipartForm == nil {
|
|
|
|
|
|
if err := that.Req.ParseMultipartForm(32 << 20); err != nil {
|
|
|
|
|
|
return nil, err
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if that.Req.MultipartForm == nil || that.Req.MultipartForm.File == nil {
|
|
|
|
|
|
return nil, http.ErrMissingFile
|
|
|
|
|
|
}
|
|
|
|
|
|
files, ok := that.Req.MultipartForm.File[name]
|
|
|
|
|
|
if !ok {
|
|
|
|
|
|
return nil, http.ErrMissingFile
|
|
|
|
|
|
}
|
|
|
|
|
|
return files, nil
|
2017-08-04 08:20:59 +00:00
|
|
|
|
}
|