github.com/zhongdalu/gf@v1.0.0/g/net/ghttp/ghttp_request.go (about) 1 // Copyright 2017 gf Author(https://github.com/zhongdalu/gf). All Rights Reserved. 2 // 3 // This Source Code Form is subject to the terms of the MIT License. 4 // If a copy of the MIT was not distributed with this file, 5 // You can obtain one at https://github.com/zhongdalu/gf. 6 7 package ghttp 8 9 import ( 10 "fmt" 11 "io/ioutil" 12 "net/http" 13 "strings" 14 15 "github.com/zhongdalu/gf/g/container/gvar" 16 "github.com/zhongdalu/gf/g/encoding/gjson" 17 "github.com/zhongdalu/gf/g/os/gtime" 18 "github.com/zhongdalu/gf/g/text/gregex" 19 ) 20 21 // 请求对象 22 type Request struct { 23 *http.Request 24 parsedGet bool // GET参数是否已经解析 25 parsedPost bool // POST参数是否已经解析 26 queryVars map[string][]string // GET参数 27 routerVars map[string][]string // 路由解析参数 28 exit bool // 是否退出当前请求流程执行 29 Id int // 请求id(唯一) 30 Server *Server // 请求关联的服务器对象 31 Cookie *Cookie // 与当前请求绑定的Cookie对象(并发安全) 32 Session *Session // 与当前请求绑定的Session对象(并发安全) 33 Response *Response // 对应请求的返回数据操作对象 34 Router *Router // 匹配到的路由对象 35 EnterTime int64 // 请求进入时间(微秒) 36 LeaveTime int64 // 请求完成时间(微秒) 37 params map[string]interface{} // 开发者自定义参数(请求流程中有效) 38 parsedHost string // 解析过后不带端口号的服务器域名名称 39 clientIp string // 解析过后的客户端IP地址 40 rawContent []byte // 客户端提交的原始参数 41 isFileRequest bool // 是否为静态文件请求(非服务请求,当静态文件存在时,优先级会被服务请求高,被识别为文件请求) 42 } 43 44 // 创建一个Request对象 45 func newRequest(s *Server, r *http.Request, w http.ResponseWriter) *Request { 46 request := &Request{ 47 routerVars: make(map[string][]string), 48 Id: s.servedCount.Add(1), 49 Server: s, 50 Request: r, 51 Response: newResponse(s, w), 52 EnterTime: gtime.Microsecond(), 53 } 54 // 会话处理 55 request.Cookie = GetCookie(request) 56 request.Session = GetSession(request) 57 request.Response.request = request 58 return request 59 } 60 61 // 获取Web Socket连接对象(如果是非WS请求会失败,注意检查返回的error结果) 62 func (r *Request) WebSocket() (*WebSocket, error) { 63 if conn, err := wsUpgrader.Upgrade(r.Response.ResponseWriter.ResponseWriter, r.Request, nil); err == nil { 64 return &WebSocket{ 65 conn, 66 }, nil 67 } else { 68 return nil, err 69 } 70 } 71 72 // 获得指定名称的参数字符串(Router/GET/POST),同 GetRequestString 73 // 这是常用方法的简化别名 74 func (r *Request) Get(key string, def ...interface{}) string { 75 return r.GetRequestString(key, def...) 76 } 77 78 // 建议都用该参数替代参数获取 79 func (r *Request) GetVar(key string, def ...interface{}) *gvar.Var { 80 return r.GetRequestVar(key, def...) 81 } 82 83 // 获取原始请求输入二进制。 84 func (r *Request) GetRaw() []byte { 85 err := error(nil) 86 if r.rawContent == nil { 87 r.rawContent, err = ioutil.ReadAll(r.Body) 88 if err != nil { 89 r.Error("error reading request body: ", err) 90 } 91 } 92 return r.rawContent 93 } 94 95 // 获取原始请求输入字符串。 96 func (r *Request) GetRawString() string { 97 return string(r.GetRaw()) 98 } 99 100 // 获取原始json请求输入字符串,并解析为json对象 101 func (r *Request) GetJson() *gjson.Json { 102 data := r.GetRaw() 103 if len(data) > 0 { 104 if j, err := gjson.DecodeToJson(data); err == nil { 105 return j 106 } else { 107 r.Error(err, ": ", string(data)) 108 } 109 } 110 return nil 111 } 112 113 func (r *Request) GetString(key string, def ...interface{}) string { 114 return r.GetRequestString(key, def...) 115 } 116 117 func (r *Request) GetInt(key string, def ...interface{}) int { 118 return r.GetRequestInt(key, def...) 119 } 120 121 func (r *Request) GetInts(key string, def ...interface{}) []int { 122 return r.GetRequestInts(key, def...) 123 } 124 125 func (r *Request) GetUint(key string, def ...interface{}) uint { 126 return r.GetRequestUint(key, def...) 127 } 128 129 func (r *Request) GetFloat32(key string, def ...interface{}) float32 { 130 return r.GetRequestFloat32(key, def...) 131 } 132 133 func (r *Request) GetFloat64(key string, def ...interface{}) float64 { 134 return r.GetRequestFloat64(key, def...) 135 } 136 137 func (r *Request) GetFloats(key string, def ...interface{}) []float64 { 138 return r.GetRequestFloats(key, def...) 139 } 140 141 func (r *Request) GetArray(key string, def ...interface{}) []string { 142 return r.GetRequestArray(key, def...) 143 } 144 145 func (r *Request) GetStrings(key string, def ...interface{}) []string { 146 return r.GetRequestStrings(key, def...) 147 } 148 149 func (r *Request) GetInterfaces(key string, def ...interface{}) []interface{} { 150 return r.GetRequestInterfaces(key, def...) 151 } 152 153 func (r *Request) GetMap(def ...map[string]string) map[string]string { 154 return r.GetRequestMap(def...) 155 } 156 157 // 将所有的request参数映射到struct属性上,参数pointer应当为一个struct对象的指针, 158 // mapping为非必需参数,自定义参数与属性的映射关系 159 func (r *Request) GetToStruct(pointer interface{}, mapping ...map[string]string) { 160 r.GetRequestToStruct(pointer, mapping...) 161 } 162 163 // 仅退出当前逻辑执行函数, 如:服务函数、HOOK函数 164 func (r *Request) Exit() { 165 panic(gEXCEPTION_EXIT) 166 } 167 168 // 退出当前请求执行,后续所有的服务逻辑流程(包括其他的HOOK)将不会执行 169 func (r *Request) ExitAll() { 170 r.exit = true 171 panic(gEXCEPTION_EXIT_ALL) 172 } 173 174 // 仅针对HOOK执行,默认情况下HOOK会按照优先级进行调用,当使用ExitHook后当前类型的后续HOOK将不会被调用 175 func (r *Request) ExitHook() { 176 panic(gEXCEPTION_EXIT_HOOK) 177 } 178 179 // 判断当前请求是否停止执行 180 func (r *Request) IsExited() bool { 181 return r.exit 182 } 183 184 // 获取请求的服务端IP/域名 185 func (r *Request) GetHost() string { 186 if len(r.parsedHost) == 0 { 187 array, _ := gregex.MatchString(`(.+):(\d+)`, r.Host) 188 if len(array) > 1 { 189 r.parsedHost = array[1] 190 } else { 191 r.parsedHost = r.Host 192 } 193 } 194 return r.parsedHost 195 } 196 197 // 判断是否为静态文件请求 198 func (r *Request) IsFileRequest() bool { 199 return r.isFileRequest 200 } 201 202 // 判断是否为AJAX请求 203 func (r *Request) IsAjaxRequest() bool { 204 return strings.EqualFold(r.Header.Get("X-Requested-With"), "XMLHttpRequest") 205 } 206 207 // 获取请求的客户端IP地址 208 func (r *Request) GetClientIp() string { 209 if len(r.clientIp) == 0 { 210 if r.clientIp = r.Header.Get("X-Real-IP"); r.clientIp == "" { 211 array, _ := gregex.MatchString(`(.+):(\d+)`, r.RemoteAddr) 212 if len(array) > 1 { 213 r.clientIp = array[1] 214 } else { 215 r.clientIp = r.RemoteAddr 216 } 217 } 218 } 219 return r.clientIp 220 } 221 222 // 获得当前请求URL地址 223 func (r *Request) GetUrl() string { 224 scheme := "http" 225 if r.TLS != nil { 226 scheme = "https" 227 } 228 return fmt.Sprintf(`%s://%s%s`, scheme, r.Host, r.URL.String()) 229 } 230 231 // 获得请求来源URL地址 232 func (r *Request) GetReferer() string { 233 return r.Header.Get("Referer") 234 }