-
Notifications
You must be signed in to change notification settings - Fork 2
/
handler.go
59 lines (51 loc) · 1.82 KB
/
handler.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
package main
import (
"fmt"
"log"
"net"
"net/http"
"strings"
)
func PathHandler(path string, pathConfig *PathConfig, nodeDB *NodeDB) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
remoteIP := net.ParseIP(req.Header.Get(*xffHeader))
if remoteIP == nil {
msg := fmt.Sprint("%s: Cannot parse IP address in %s header", req.URL.Path, *xffHeader)
log.Println(msg)
http.Error(w, msg, http.StatusInternalServerError)
return
}
var node *Node
RulesLoop:
for _, rule := range pathConfig.Rules {
if node == nil && (len(rule.When) != 0 || rule.Careful) {
node = nodeDB.GetNode(remoteIP)
if node == nil {
log.Printf("%s %s: Node not found in node DB, cannot evaluate rule", remoteIP, req.URL.Path)
continue
}
log.Printf("%s %s: Identified node %s", remoteIP, req.URL.Path, node.Nodeinfo.Hostname)
}
for _, condition := range rule.When {
if !condition.Check(node.Nodeinfo) {
continue RulesLoop
}
log.Printf("%s %s: Field '%s' matches '%s'", remoteIP, req.URL.Path, condition.Field, condition.Match)
}
if rule.Careful && !node.HasOnlyVPNLinks() {
log.Printf("%s %s: Careful enabled and node is not VPN only, skipping rule", remoteIP, req.URL.Path)
continue
}
if rule.Disabled {
log.Printf("%s %s: Matching rule is DISABLED: %s -> %s", remoteIP, req.URL.Path, path, rule.Path)
continue
}
log.Printf("%s %s: Using redirect rule %s -> %s", remoteIP, req.URL.Path, path, rule.Path)
w.Header().Set(*redirectHeader, fmt.Sprint(rule.Path, strings.TrimPrefix(req.URL.Path, path)))
return
}
log.Printf("%s %s: Using default redirect %s -> %s", remoteIP, req.URL.Path, path, pathConfig.Default)
w.Header().Set(*redirectHeader, fmt.Sprint(pathConfig.Default, strings.TrimPrefix(req.URL.Path, path)))
return
})
}