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  }