-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmiddleware.go
129 lines (113 loc) · 3.09 KB
/
middleware.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
127
128
129
package httpclient
import (
"crypto/tls"
"errors"
"io"
"io/ioutil"
"net"
"net/http"
"time"
)
//var dNSPool = []string{"1.1.1.1", "1.0.0.1", "9.9.9.9", "8.8.8.8", "8.8.4.4", "208.67.222.222", "208.67.222.222"}
type redirects struct {
Count int
Urls []string
StatusCodes []int
Sizes []int
}
type middleware struct {
transport http.Transport
redirects *redirects
analyzer bool
maxRetry int
readTimeout time.Duration
maxBodySize int64
}
func (m middleware) appendRedirect(url string, statuscode int, size int) {
m.redirects.Count += 1
m.redirects.Urls = append(m.redirects.Urls, url)
m.redirects.StatusCodes = append(m.redirects.StatusCodes, statuscode)
m.redirects.Sizes = append(m.redirects.Sizes, size)
}
func (m middleware) analyze(r *Response) {
//TODO detect some security bugs
return
}
func (m middleware) RoundTrip(req *http.Request) (resp *http.Response, err error) {
transport := m.transport
//proxyUrl, _ := url.Parse("http://127.0.0.1:8080")
//transport.Proxy = http.ProxyURL(proxyUrl)
transport.MaxIdleConns = 2000
transport.MaxIdleConnsPerHost = 1000
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true, Renegotiation: tls.RenegotiateOnceAsClient}
transport.DisableKeepAlives = true
transport.DialContext = (&net.Dialer{
Timeout: 10 * time.Second,
KeepAlive: 1 * time.Second,
//TODO fix memory leak
//Resolver: &net.Resolver{
//PreferGo: true,
//Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
// d := net.Dialer{
// Timeout: time.Second * 10,
// }
// return d.DialContext(ctx, "udp", "8.8.8.8:53")
//for {
// ctx,_ = context.WithDeadline(context.Background(), time.Now().Local().Add(time.Hour * time.Duration(0) +
// time.Minute * time.Duration(0) +
// time.Second * time.Duration(10)))
// conn, err := d.DialContext(ctx, "udp", DNSPool[rand.Intn(len(DNSPool))]+":53") //memory leak
// if err != nil {
// fmt.Println(err.Error())
// time.Sleep(time.Second)
// continue
// }
// return conn, nil
//}
//},
//},
}).DialContext
transport.TLSHandshakeTimeout = 10 * time.Second
transport.IdleConnTimeout = 30 * time.Second
transport.ExpectContinueTimeout = 5 * time.Second
transport.ResponseHeaderTimeout = 10 * time.Second
transport.DisableCompression = true
var retryed = 0
for {
resp, err = transport.RoundTrip(req)
if err != nil {
if retryed == m.maxRetry {
return
}
retryed += 1
continue
} else {
break
}
}
//prevent redirect to other domain...
if req.Response != nil && req.Response.Request != nil {
if !match(*req.URL, *req.Response.Request.URL) {
resp.Body.Close()
return resp, errors.New(redirectOutMessage)
}
}
if resp.StatusCode > 299 && resp.StatusCode < 400 {
var body []byte
readDone := make(chan int)
go func() {
body, _ = ioutil.ReadAll(io.LimitReader(resp.Body, m.maxBodySize))
readDone <- 1
}()
select {
case <-time.After(m.readTimeout):
//deadline
case <-readDone:
}
resp.Body.Close()
size := len(body)
m.appendRedirect(req.URL.String(), resp.StatusCode, size)
resp.Body.Close()
}
return
}