diff options
-rw-r--r-- | main.go | 134 |
1 files changed, 87 insertions, 47 deletions
@@ -11,62 +11,102 @@ import ( ) -//type Endpoint struct { -// path string -// address string -//} -// -// -//func proxy(w http.ResponseWriter, req *http.Request, end Endpoint) { -//} -// -//func makeProxiedRequest(w http.ResponseWriter, req *http.Request, end Endpoint) { -// -//} -// - func main() { const addr = "localhost:3333" + log.Info("configuring reverse proxy...") - origin, err := url.Parse("http://localhost:8000") + configureEndpoint("/proxy1", "http://localhost:8000") + + log.Infof("serving on %v", addr) + log.Fatal(http.ListenAndServe(addr, nil)) +} + + +type Endpoint struct { + Path string + Origin *url.URL +} + + +func configureEndpoint(path, address string) { + log.Infof("proxying endpoint %v to %v", path, address) + origin, err := url.Parse(address) if err != nil { log.Fatal(err) } - log.Infof("listening on %v", addr) - http.ListenAndServe(addr, http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - req.Host = origin.Host - req.URL.Host = origin.Host - req.URL.Scheme = origin.Scheme - req.RequestURI = "" - // set X-Forwarded-For - forwardedFor, _, _ := net.SplitHostPort(req.RemoteAddr) - req.Header.Set("X-Forwarded-For", forwardedFor) - response, err := http.DefaultClient.Do(req) - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - fmt.Fprintf(w, "%v", err) - log.Fatal(err) - } - // copy header - for key, values := range response.Header { - for _, value := range values { - w.Header().Add(key, value) - } - } + end := Endpoint{ + Path: path, + Origin: origin, + } - // get trailer keys - trailerKeys := []string{} - for key := range response.Trailer { - trailerKeys = append(trailerKeys, key) - } - if (len(trailerKeys) > 0) { - w.Header().Set("Trailer", strings.Join(trailerKeys, ",")) + http.HandleFunc(path + "/", func(w http.ResponseWriter, req *http.Request) { + log.Infof("REQ: %v", req.URL.Path) + proxy(w, req, end) + }) +} + + +func proxy(w http.ResponseWriter, req *http.Request, end Endpoint) { + response := proxyRequest(w, req, end) + proxyResponse(w, response) +} + + +func proxyRequest(w http.ResponseWriter, req *http.Request, end Endpoint) *http.Response { + // configure host address + req.Host = end.Origin.Host + req.URL.Host = end.Origin.Host + + // strip proxy endpoint path from request path + req.URL.Path = strings.TrimPrefix(req.URL.Path, end.Path) + + // set X-Forwarded-For + forwardedFor, _, _ := net.SplitHostPort(req.RemoteAddr) + req.Header.Set("X-Forwarded-For", forwardedFor) + + // misc request cleanups + req.URL.Scheme = end.Origin.Scheme + req.RequestURI = "" + + // make request + response, err := http.DefaultClient.Do(req) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + fmt.Fprintf(w, "%v", err) + log.Fatal(err) + } + + return response +} + + +func proxyResponse(w http.ResponseWriter, response *http.Response) { + // copy header + for key, values := range response.Header { + for _, value := range values { + w.Header().Add(key, value) } + } - w.WriteHeader(response.StatusCode) + // get trailer keys + trailerKeys := []string{} + for key := range response.Trailer { + trailerKeys = append(trailerKeys, key) + } + if (len(trailerKeys) > 0) { + w.Header().Set("Trailer", strings.Join(trailerKeys, ",")) + } - // copy body - io.Copy(w, response.Body) - })) + w.WriteHeader(response.StatusCode) + + // copy body to client + io.Copy(w, response.Body) + + // write trailers + for key, values := range response.Trailer { + for _, value := range values { + w.Header().Set(key, value) + } + } } |