-
Notifications
You must be signed in to change notification settings - Fork 0
/
responsive.go
96 lines (84 loc) · 2.37 KB
/
responsive.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
package squidr
import (
"bytes"
"io"
"net/http"
"sync"
"time"
)
var responders, failed sync.Map // cache connectivity state
func isReachableViaProxy(targetMap rMap, idx int) bool {
// check cache state
target := targetMap.targets[idx]
if _, ok := failed.Load(target); ok {
return fail(target)
}
if _, ok := responders.Load(target); ok {
return responsive(target)
}
// setup new https request
client := getClient(getTransportProxy(_proxyURL, getTlsConf(proxyTrust)))
request, err := getRequest(_https+target+targetMap.validateURL, _userAgent)
if err != nil {
return false
}
// get head first, warm caches
request.Method = "HEAD"
client.Timeout = time.Duration(5 * time.Second)
resp, err := client.Do(request)
if targetMap.headerOnly {
if err != nil || resp.StatusCode != 200 || invalidBodySize(resp, targetMap) {
return fail(target)
}
return responsive(target)
}
// get validateURL
request.Method = "GET"
client.Timeout = time.Duration(6 * time.Second)
resp, err = client.Do(request)
if err != nil || resp.StatusCode != 200 || invalidBodySize(resp, targetMap) || isInternalErrPage(resp) {
return fail(target)
}
// reachable
return responsive(target)
}
// isInternalErrPage response true if answer is an silent redirect to interal error
func isInternalErrPage(resp *http.Response) bool {
head := make([]byte, _checkHeadLen)
if _, err := io.ReadAtLeast(resp.Body, head, _checkHeadLen); err != nil {
return false
}
defer resp.Body.Close()
return bytes.Equal(head, []byte(_head))
}
// invalidBodySize response true if size requirement switch on an not meet
func invalidBodySize(resp *http.Response, targetMap rMap) bool {
if targetMap.minSize < resp.ContentLength {
return false
}
body, err := decodeResponse(resp)
if err != nil {
debugLogChan <- "### INTERNAL ERROR: unable to read or decompress response" + err.Error()
return false
}
if targetMap.minSize < int64(len(body)) {
return false
}
return true
}
// fail returns always false, syncs fail/responders stores for target
func fail(target string) bool {
failed.Store(target, true)
if _, ok := responders.Load(target); ok {
responders.Delete(target)
}
return false
}
// responsive returns always true, syncs fail/responders stores for target
func responsive(target string) bool {
responders.Store(target, true)
if _, ok := failed.Load(target); ok {
failed.Delete(target)
}
return true
}