-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproxy.go
More file actions
100 lines (82 loc) · 2.28 KB
/
proxy.go
File metadata and controls
100 lines (82 loc) · 2.28 KB
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
package portpxy
import (
"fmt"
"net/http"
"net/http/httputil"
"net/url"
"strconv"
"strings"
"time"
"github.com/prometheus/client_golang/prometheus"
"go.uber.org/zap"
)
// Pmx struct for storing metrics
type Pmx struct {
Requests prometheus.Counter
Latency prometheus.Summary
}
type Proxy struct {
BackendHost string
BackendProto string
AllowRangeBegin int
AllowRangeEnd int
Logger *zap.Logger
Pmx *Pmx
}
// Handle proxy requests
func (p *Proxy) Handle(w http.ResponseWriter, r *http.Request) {
var admit = true
p.Pmx.Requests.Inc()
start := time.Now()
reqPath := strings.TrimLeft(r.URL.Path, "/")
reqMethod := r.Method
backend := fmt.Sprintf("%s://%s", p.BackendProto, p.BackendHost)
port := ""
pathParts := strings.Split(reqPath, "/")
port = pathParts[0]
portInt, err := strconv.Atoi(port)
if err != nil {
admit = false
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
_, _ = w.Write([]byte("{\"status\": \"port must be a number\"}"))
}
if admit && (portInt < p.AllowRangeBegin || portInt > p.AllowRangeEnd) {
admit = false
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
_, _ = w.Write([]byte("{\"status\": \"port must be in range\"}"))
}
if admit {
backend = fmt.Sprintf("%s:%s", backend, port)
// Backend Configuration
targetUrl, err := url.Parse(backend)
if err != nil {
admit = false
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusBadRequest)
_, _ = w.Write([]byte("{\"status\": \"unable to parse URL\"}"))
}
if admit {
r.RequestURI = strings.Replace(r.RequestURI, "/"+port, "", 1)
r.URL, _ = url.Parse(r.RequestURI)
r.Host = fmt.Sprintf("%s:%s", p.BackendHost, port)
// PROXY REQUEST
pxy := httputil.NewSingleHostReverseProxy(targetUrl)
pxy.ServeHTTP(w, r)
}
}
end := time.Now()
p.Pmx.Latency.Observe(float64(end.Sub(start)))
p.Logger.Info("Proxy Result",
zap.String("r.URL", r.URL.String()),
zap.String("r.Host", r.Host),
zap.String("backend", backend),
zap.String("method", reqMethod),
zap.String("path", reqPath),
zap.String("time", end.Format(time.RFC3339)),
zap.Any("header", r.Header),
zap.Any("URL", r.URL),
zap.Any("RequestURI", r.RequestURI),
)
}