package main import ( "io" "log" "net" "net/http" "strings" "gfx.cafe/open/gun" ) var Config struct { Port string Root string } func init() { gun.Load(&Config) if Config.Port == "" { Config.Port = "8080" } if Config.Root == "" { Config.Root = "./dist" } } var hopHeaders = []string{ "Connection", "Keep-Alive", "Proxy-Authenticate", "Proxy-Authorization", "Te", "Trailers", "Transfer-Encoding", "Upgrade", } func appendHostToXForwardHeader(header http.Header, host string) { if prior, ok := header["X-Forwarded-For"]; ok { host = strings.Join(prior, ", ") + ", " + host } header.Set("X-Forwarded-For", host) } 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) } } type Handler struct { c http.Client } func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { if strings.HasPrefix(strings.TrimPrefix("/", r.URL.Path), "lifeto") { h.handleProxy(w, r) return } h.handleProxy(w, r) } func (h *Handler) handleProxy(w http.ResponseWriter, r *http.Request) { r.RequestURI = "" if clientIP, _, err := net.SplitHostPort(r.RemoteAddr); err == nil { appendHostToXForwardHeader(r.Header, clientIP) } resp, err := h.c.Do(r) if err != nil { http.Error(w, "Server Error", http.StatusInternalServerError) log.Println("ServeHTTP:", err) } defer resp.Body.Close() delHopHeaders(resp.Header) copyHeader(w.Header(), resp.Header) w.WriteHeader(resp.StatusCode) io.Copy(w, resp.Body) } func (h *Handler) handleSite(w http.ResponseWriter, r *http.Request) { http.StripPrefix(Config.Root, http.FileServer(http.Dir(Config.Root))).ServeHTTP(w, r) } func main() { log.Printf("starting with config: %+v", Config) http.ListenAndServe(":"+Config.Port, &Handler{}) }