...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package httpproxy
16
17 import (
18 "encoding/json"
19 "net/http"
20 "strings"
21 "time"
22
23 "go.uber.org/zap"
24 "golang.org/x/net/http2"
25 )
26
27 const (
28
29
30
31
32
33
34
35 DefaultMaxIdleConnsPerHost = 128
36 )
37
38
39
40
41
42 type GetProxyURLs func() []string
43
44
45
46
47 func NewHandler(lg *zap.Logger, t *http.Transport, urlsFunc GetProxyURLs, failureWait time.Duration, refreshInterval time.Duration) http.Handler {
48 if lg == nil {
49 lg = zap.NewNop()
50 }
51 if t.TLSClientConfig != nil {
52
53 err := http2.ConfigureTransport(t)
54 if err != nil {
55 lg.Info("Error enabling Transport HTTP/2 support", zap.Error(err))
56 }
57 }
58
59 p := &reverseProxy{
60 lg: lg,
61 director: newDirector(lg, urlsFunc, failureWait, refreshInterval),
62 transport: t,
63 }
64
65 mux := http.NewServeMux()
66 mux.Handle("/", p)
67 mux.HandleFunc("/v2/config/local/proxy", p.configHandler)
68
69 return mux
70 }
71
72
73 func NewReadonlyHandler(hdlr http.Handler) http.Handler {
74 readonly := readonlyHandlerFunc(hdlr)
75 return http.HandlerFunc(readonly)
76 }
77
78 func readonlyHandlerFunc(next http.Handler) func(http.ResponseWriter, *http.Request) {
79 return func(w http.ResponseWriter, req *http.Request) {
80 if req.Method != "GET" {
81 w.WriteHeader(http.StatusNotImplemented)
82 return
83 }
84
85 next.ServeHTTP(w, req)
86 }
87 }
88
89 func (p *reverseProxy) configHandler(w http.ResponseWriter, r *http.Request) {
90 if !allowMethod(w, r.Method, "GET") {
91 return
92 }
93
94 eps := p.director.endpoints()
95 epstr := make([]string, len(eps))
96 for i, e := range eps {
97 epstr[i] = e.URL.String()
98 }
99
100 proxyConfig := struct {
101 Endpoints []string `json:"endpoints"`
102 }{
103 Endpoints: epstr,
104 }
105
106 json.NewEncoder(w).Encode(proxyConfig)
107 }
108
109
110
111
112 func allowMethod(w http.ResponseWriter, m string, ms ...string) bool {
113 for _, meth := range ms {
114 if m == meth {
115 return true
116 }
117 }
118 w.Header().Set("Allow", strings.Join(ms, ","))
119 http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
120 return false
121 }
122
View as plain text