package main // import "github.com/crosbymichael/dockerui" import ( "flag" "io" "log" "net" "net/http" "net/http/httputil" "net/url" "os" "strings" "github.com/gorilla/csrf" ) var ( endpoint = flag.String("e", "/var/run/docker.sock", "Dockerd endpoint") addr = flag.String("p", ":9000", "Address and port to serve dockerui") assets = flag.String("a", ".", "Path to the assets") CSRF = csrf.Protect( []byte("32-byte-long-auth-key"), // FIXME: generate once, reuse on restarts csrf.HttpOnly(false), csrf.Secure(false), ) ) type UnixHandler struct { path string } func (h *UnixHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { conn, err := net.Dial("unix", h.path) if err != nil { w.WriteHeader(http.StatusInternalServerError) log.Println(err) return } c := httputil.NewClientConn(conn, nil) defer c.Close() res, err := c.Do(r) if err != nil { w.WriteHeader(http.StatusInternalServerError) log.Println(err) return } defer res.Body.Close() copyHeader(w.Header(), res.Header) if _, err := io.Copy(w, res.Body); err != nil { log.Println(err) } } func copyHeader(dst, src http.Header) { for k, vv := range src { for _, v := range vv { dst.Add(k, v) } } } func createTcpHandler(e string) http.Handler { u, err := url.Parse(e) if err != nil { log.Fatal(err) } return httputil.NewSingleHostReverseProxy(u) } func createUnixHandler(e string) http.Handler { return &UnixHandler{e} } func createHandler(dir string, e string) http.Handler { var ( mux = http.NewServeMux() fileHandler = http.FileServer(http.Dir(dir)) h http.Handler ) if strings.Contains(e, "http") { h = createTcpHandler(e) } else { if _, err := os.Stat(e); err != nil { if os.IsNotExist(err) { log.Fatalf("unix socket %s does not exist", e) } log.Fatal(err) } h = createUnixHandler(e) } mux.Handle("/dockerapi/", http.StripPrefix("/dockerapi", h)) mux.Handle("/", fileHandler) return logWrapper(CSRF(mux)) } func logWrapper(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { log.Println("Request starting: " + r.URL.Path) c, err := r.Cookie ("_gorilla_csrf") if err != nil { log.Println("Unable to find session cookie _gorilla_csrf") h.ServeHTTP(w, r) } else { log.Println("Cookie:" + c.Value) log.Println("Header:" + r.Header.Get("X-CSRF-Token")) h.ServeHTTP(w, r) log.Println("Request ending") } }) } func main() { flag.Parse() handler := createHandler(*assets, *endpoint) if err := http.ListenAndServe(*addr, handler); err != nil { log.Fatal(err) } }