-
-
Save chrisdd2/b33b69552d5d8f3cef8e96963f0049b0 to your computer and use it in GitHub Desktop.
proxy with a map
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "fmt" | |
| "io" | |
| "log" | |
| "net/http" | |
| "net/url" | |
| "os" | |
| "strings" | |
| ) | |
| type MappedProxy struct { | |
| hosts map[string]*url.URL | |
| } | |
| func copyHeader(src http.Header, tgt http.Header) { | |
| for k, vv := range src { | |
| for _, v := range vv { | |
| tgt.Add(k, v) | |
| } | |
| } | |
| } | |
| func (s *MappedProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) { | |
| // get mapping | |
| mappedHost, ok := s.hosts[r.Host] | |
| if !ok { | |
| http.Error(w, "mapping not found", http.StatusNotFound) | |
| return | |
| } | |
| // create request with mapped host | |
| targetUrl := mappedHost.ResolveReference(&url.URL{Path: r.URL.Path, RawQuery: r.URL.RawQuery}) | |
| req, err := http.NewRequest(r.Method, targetUrl.String(), r.Body) | |
| if err != nil { | |
| http.Error(w, fmt.Sprintf("unable to create request [%s]", err), http.StatusInternalServerError) | |
| return | |
| } | |
| log.Printf("redirecting [%s] [%s] to [%s]", r.Host, r.URL.String(), targetUrl.String()) | |
| copyHeader(r.Header, req.Header) | |
| req.Host = mappedHost.Host | |
| // perform and hope | |
| resp, err := http.DefaultClient.Do(req) | |
| if err != nil { | |
| http.Error(w, fmt.Sprintf("proxy error [%s]", err), http.StatusInternalServerError) | |
| return | |
| } | |
| defer resp.Body.Close() | |
| copyHeader(w.Header(), resp.Header) | |
| w.WriteHeader(resp.StatusCode) | |
| io.Copy(w, resp.Body) | |
| } | |
| func main() { | |
| addr := os.Getenv("APP_LISTEN_ADDR") | |
| sourceHost := strings.Split(os.Getenv("APP_SOURCE_HOSTS"), ",") | |
| targetHosts := strings.Split(os.Getenv("APP_TARGET_HOSTS"), ",") | |
| if len(sourceHost) != len(targetHosts) { | |
| log.Fatalln("source target hosts mismatch") | |
| } | |
| mustParse := func(u string) *url.URL { | |
| ret, err := url.Parse(u) | |
| if err != nil { | |
| panic(err.Error()) | |
| } | |
| return ret | |
| } | |
| proxy := MappedProxy{hosts: make(map[string]*url.URL)} | |
| for i := 0; i < len(sourceHost); i++ { | |
| proxy.hosts[sourceHost[i]] = mustParse(targetHosts[i]) | |
| } | |
| log.Printf("listening on [%s]\n", addr) | |
| if err := http.ListenAndServe(addr, &proxy); err != nil { | |
| log.Fatalln(err) | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment