package main import ( "flag" "io" "log" "net" "net/http" "strings" "net/url" ) // Hop-by-hop headers. These are removed when sent to the backend. // http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html var hopHeaders = []string{ "Connection", "Keep-Alive", "Proxy-Authenticate", "Proxy-Authorization", "Te", // canonicalized version of "TE" "Trailers", "Transfer-Encoding", "Upgrade", } func copyHeader(dst, src http.Header) { for k, vv := range src { for _, v := range vv { dst.Add(k, v) } } } func delHopHeaders(header http.Header) { for _, h := range hopHeaders { header.Del(h) } } func appendHostToXForwardHeader(header http.Header, host string) { // If we aren't the first proxy retain prior // X-Forwarded-For information as a comma+space // separated list and fold multiple headers into one. if prior, ok := header["X-Forwarded-For"]; ok { host = strings.Join(prior, ", ") + ", " + host } header.Set("X-Forwarded-For", host) } type proxy struct { ns string svc string } func (p *proxy) ServeHTTP(wr http.ResponseWriter, req *http.Request) { log.Println(req.RemoteAddr, " ", req.Method, " ", req.URL) /*if req.URL.Scheme != "http" && req.URL.Scheme != "https" { msg := "unsupported protocal scheme "+req.URL.Scheme http.Error(wr, msg, http.StatusBadRequest) log.Println(msg) return }*/ client := &http.Client{} //http: Request.RequestURI can't be set in client requests. //http://golang.org/src/pkg/net/http/client.go req.RequestURI = "" u, err := url.Parse("http://127.0.0.1:8001/api/v1/namespaces/" + p.ns + "/services/" + p.svc + "/proxy" + req.URL.RequestURI()) if err != nil { http.Error(wr, "Server Error", http.StatusInternalServerError) log.Fatal("ServeHTTP:", err) } req.URL = u delHopHeaders(req.Header) if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil { appendHostToXForwardHeader(req.Header, clientIP) } resp, err := client.Do(req) if err != nil { http.Error(wr, "Server Error", http.StatusInternalServerError) log.Fatal("ServeHTTP:", err) } defer resp.Body.Close() log.Println(req.RemoteAddr, " ", resp.Status) delHopHeaders(resp.Header) copyHeader(wr.Header(), resp.Header) wr.WriteHeader(resp.StatusCode) io.Copy(wr, resp.Body) } func main() { var addr = flag.String("addr", "127.0.0.1:8002", "The addr of the application.") var namespace = flag.String("ns", "longhorn-system", "Kube namespace") var service = flag.String("svc", "longhorn-frontend:longhorn-ui", "Kube service") flag.Parse() handler := &proxy{ns: *namespace, svc: *service} log.Println("Starting proxy server on", *addr) if err := http.ListenAndServe(*addr, handler); err != nil { log.Fatal("ListenAndServe:", err) } }