forked from getfider/fider
-
Notifications
You must be signed in to change notification settings - Fork 0
/
request.go
108 lines (91 loc) · 2.87 KB
/
request.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
package web
import (
"io/ioutil"
"net"
"net/http"
"net/url"
"regexp"
"strings"
"github.com/getfider/fider/app/pkg/errors"
)
//Request wraps the http request object
type Request struct {
instance *http.Request
Method string
ClientIP string
ContentLength int64
Body string
IsSecure bool
URL *url.URL
}
// WrapRequest returns Fider wrapper of HTTP Request
func WrapRequest(request *http.Request) Request {
protocol := "http"
if request.TLS != nil || request.Header.Get("X-Forwarded-Proto") == "https" {
protocol = "https"
}
host := request.Host
if request.Header.Get("X-Forwarded-Host") != "" {
host = request.Header.Get("X-Forwarded-Host")
}
fullURL := protocol + "://" + host + request.RequestURI
u, err := url.Parse(fullURL)
if err != nil {
panic(errors.Wrap(err, "Failed to parse url '%s'", fullURL))
}
var bodyBytes []byte
if request.ContentLength > 0 {
bodyBytes, err = ioutil.ReadAll(request.Body)
if err != nil {
panic(errors.Wrap(err, "failed to read body").Error())
}
}
clientIP := getClientIP(request)
return Request{
instance: request,
Method: request.Method,
ClientIP: strings.TrimSpace(clientIP),
ContentLength: request.ContentLength,
Body: string(bodyBytes),
URL: u,
IsSecure: protocol == "https",
}
}
// getClientIP returns the IP of the original requestor.
func getClientIP(request *http.Request) (clientIP string) {
if forwardedHosts := request.Header.Get("X-Forwarded-For"); forwardedHosts != "" {
clientIP = strings.Split(forwardedHosts, ",")[0]
} else {
clientIP, _, _ = net.SplitHostPort(request.RemoteAddr)
}
return
}
// GetHeader returns the value of HTTP header from given key
func (r *Request) GetHeader(key string) string {
return r.instance.Header.Get(key)
}
// SetHeader updates the value of HTTP header of given key
func (r *Request) SetHeader(key, value string) {
r.instance.Header.Set(key, value)
}
// Cookie returns the named cookie provided in the request.
func (r *Request) Cookie(name string) (*http.Cookie, error) {
cookie, err := r.instance.Cookie(name)
if err != nil {
return nil, errors.Wrap(err, "failed to get '%s' cookie", name)
}
return cookie, nil
}
// AddCookie adds a cookie
func (r *Request) AddCookie(cookie *http.Cookie) {
r.instance.AddCookie(cookie)
}
// IsAPI returns true if its a request for an API resource
func (r *Request) IsAPI() bool {
return strings.HasPrefix(r.URL.Path, "/api/")
}
var crawlerRegex = regexp.MustCompile("(?i)(baidu)|(msnbot)|(bingbot)|(bingpreview)|(duckduckbot)|(googlebot)|(adsbot-google)|(mediapartners-google)|(slurp)|(yandexbot)|(yandexmetrika)|(ahrefsbot)|(twitterbot)|(slackbot)|(discordbot)|(semrushBot)|(exabot)")
// IsCrawler returns true if the request is coming from a crawler
func (r *Request) IsCrawler() bool {
return crawlerRegex.MatchString(r.GetHeader("User-Agent"))
}