github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/depends/kit/httptransport/httpx/httpx_request_info.go (about) 1 package httpx 2 3 import ( 4 "context" 5 "io" 6 "net/http" 7 "net/textproto" 8 "net/url" 9 "strings" 10 "time" 11 12 "github.com/julienschmidt/httprouter" 13 ) 14 15 func NewRequestInfo(r *http.Request) RequestInfo { 16 return &requestInfo{ 17 recvts: time.Now(), 18 request: r, 19 } 20 } 21 22 type WithFromRequestInfo interface { 23 FromRequestInfo(ri RequestInfo) error 24 } 25 26 type RequestInfo interface { 27 Context() context.Context 28 Values(in string, name string) []string 29 Header() http.Header 30 Body() io.ReadCloser 31 } 32 33 type requestInfo struct { 34 request *http.Request 35 recvts time.Time 36 query url.Values 37 cookies []*http.Cookie 38 params httprouter.Params 39 } 40 41 func (ri *requestInfo) Header() http.Header { return ri.request.Header } 42 43 func (ri *requestInfo) Context() context.Context { return ri.request.Context() } 44 45 func (ri *requestInfo) Body() io.ReadCloser { return ri.request.Body } 46 47 func (ri *requestInfo) Value(in string, name string) string { 48 values := ri.Values(in, name) 49 if len(values) == 0 { 50 return "" 51 } 52 return values[0] 53 } 54 55 func (ri *requestInfo) Values(in string, name string) []string { 56 switch in { 57 case "path": 58 v := ri.Param(name) 59 if v == "" { 60 return []string{} 61 } 62 return []string{v} 63 case "query": 64 return ri.QueryValues(name) 65 case "cookie": 66 return ri.CookieValues(name) 67 case "header": 68 return ri.HeaderValues(name) 69 } 70 return []string{} 71 } 72 73 func (ri *requestInfo) Param(name string) string { 74 if ri.params == nil { 75 params, ok := ri.request.Context().Value(httprouter.ParamsKey).(httprouter.Params) 76 if !ok { 77 params = httprouter.Params{} 78 } 79 ri.params = params 80 } 81 return ri.params.ByName(name) 82 } 83 84 func (ri *requestInfo) QueryValues(name string) []string { 85 if ri.query == nil { 86 ri.query = ri.request.URL.Query() 87 88 if ri.request.Method == http.MethodGet && len(ri.query) == 0 && 89 ri.request.ContentLength > 0 { 90 if strings.HasPrefix(ri.request.Header.Get("Content-Type"), MIME_FORM_URLENCODED) { 91 data, err := io.ReadAll(ri.request.Body) 92 if err == nil { 93 ri.request.Body.Close() 94 95 query, e := url.ParseQuery(string(data)) 96 if e == nil { 97 ri.query = query 98 } 99 } 100 } 101 } 102 } 103 return ri.query[name] 104 } 105 106 func (ri *requestInfo) HeaderValues(name string) []string { 107 return ri.request.Header[textproto.CanonicalMIMEHeaderKey(name)] 108 } 109 110 func (ri *requestInfo) CookieValues(name string) []string { 111 if ri.cookies == nil { 112 ri.cookies = ri.request.Cookies() 113 } 114 115 values := make([]string, 0) 116 for _, c := range ri.cookies { 117 if c.Name == name { 118 if c.Expires.IsZero() { 119 values = append(values, c.Value) 120 } else if c.Expires.After(ri.recvts) { 121 values = append(values, c.Value) 122 } 123 } 124 } 125 return values 126 }