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