From b2054096792b0547cedcaffa766b198a91c83d55 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Mon, 21 Jan 2019 11:36:52 +0100 Subject: [PATCH] dashboard: add the ability to use a remote dashboard, serve only local files: assets and eventualy public.json (to override given ones) --- dashboard/fwd.go | 50 +++++++++++++++++++ dashboard/main.go | 5 ++ dashboard/static.go | 119 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 154 insertions(+), 20 deletions(-) create mode 100644 dashboard/fwd.go diff --git a/dashboard/fwd.go b/dashboard/fwd.go new file mode 100644 index 00000000..9514a134 --- /dev/null +++ b/dashboard/fwd.go @@ -0,0 +1,50 @@ +package main + +import ( + "io" + "net/http" + "net/url" + "os" + "path" +) + +func fwd_request(w http.ResponseWriter, r *http.Request, fwd string) { + if u, err := url.Parse(fwd); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } else { + var user, pass string + if u.User != nil { + user = u.User.Username() + pass, _ = u.User.Password() + u.User = nil + } + if v, exists := os.LookupEnv("FICCLOUD_USER"); exists { + user = v + } else if v, exists := os.LookupEnv("FICCLOUD_PASS"); exists { + pass = v + } + + u.Path = path.Join(u.Path, r.URL.Path) + + if r, err := http.NewRequest(r.Method, u.String(), r.Body); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } else { + if len(user) != 0 || len(pass) != 0 { + r.SetBasicAuth(user, pass) + } + + if resp, err := http.DefaultClient.Do(r); err != nil { + http.Error(w, err.Error(), http.StatusBadGateway) + } else { + defer resp.Body.Close() + + for key := range resp.Header { + w.Header().Add(key, resp.Header.Get(key)) + } + w.WriteHeader(resp.StatusCode) + + io.Copy(w, resp.Body) + } + } + } +} diff --git a/dashboard/main.go b/dashboard/main.go index 2c8b1062..fadc3d09 100644 --- a/dashboard/main.go +++ b/dashboard/main.go @@ -72,6 +72,8 @@ func main() { flag.StringVar(&DashboardDir, "dashbord", "./DASHBOARD", "Base directory where save public JSON files") flag.StringVar(&TeamsDir, "teams", "./TEAMS", "Base directory where save teams JSON files") flag.StringVar(&settings.SettingsDir, "settings", settings.SettingsDir, "Base directory where load and save settings") + var fwdr = flag.String("forwarder", "", "URL of another dashboard where send traffic to, except static assets") + flag.BoolVar(&fwdPublicJson, "fwdpublicjson", fwdPublicJson, "Also forward public.json files to forwarder") flag.Parse() log.SetPrefix("[public] ") @@ -95,6 +97,9 @@ func main() { tmp := "" baseURL = &tmp } + if fwdr != nil && len(*fwdr) > 0 { + forwarder = fwdr + } // Prepare graceful shutdown interrupt := make(chan os.Signal, 1) diff --git a/dashboard/static.go b/dashboard/static.go index 5950f065..ffa26e1a 100644 --- a/dashboard/static.go +++ b/dashboard/static.go @@ -14,6 +14,9 @@ import ( "github.com/julienschmidt/httprouter" ) +var forwarder *string = nil +var fwdPublicJson = false + func init() { api.Router().GET("/", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { http.ServeFile(w, r, path.Join(StaticDir, "index.html")) @@ -36,80 +39,156 @@ func init() { }) api.Router().GET("/files/*_", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { - http.ServeFile(w, r, path.Join(fic.FilesDir, strings.TrimPrefix(r.URL.Path, "/files"))) + if forwarder != nil { + fwd_request(w, r, *forwarder) + } else { + http.ServeFile(w, r, path.Join(fic.FilesDir, strings.TrimPrefix(r.URL.Path, "/files"))) + } }) api.Router().GET("/events.json", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { w.Header().Set("Cache-Control", "no-cache") - http.ServeFile(w, r, path.Join(TeamsDir, "events.json")) + if forwarder != nil { + fwd_request(w, r, *forwarder) + } else { + http.ServeFile(w, r, path.Join(TeamsDir, "events.json")) + } }) api.Router().GET("/my.json", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { w.Header().Set("Cache-Control", "no-cache") - http.ServeFile(w, r, path.Join(TeamsDir, "public", "my.json")) + if forwarder != nil { + fwd_request(w, r, *forwarder) + } else { + http.ServeFile(w, r, path.Join(TeamsDir, "public", "my.json")) + } }) api.Router().GET("/stats.json", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { w.Header().Set("Cache-Control", "no-cache") - http.ServeFile(w, r, path.Join(TeamsDir, "public", "stats.json")) + if forwarder != nil { + fwd_request(w, r, *forwarder) + } else { + http.ServeFile(w, r, path.Join(TeamsDir, "public", "stats.json")) + } }) api.Router().GET("/api/teams/:tid/stats.json", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { - http.Redirect(w, r, "http://127.0.0.1:8081/api/teams/" + string(ps.ByName("tid")) + "/stats.json", 302) + if forwarder != nil { + fwd_request(w, r, *forwarder) + } else { + fwd_request(w, r, "http://127.0.0.1:8081/") + } }) api.Router().GET("/settings.json", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { - w.Header().Set("X-FIC-Time", fmt.Sprintf("%f", float64(time.Now().UnixNano()/1000)/1000000)) w.Header().Set("Cache-Control", "no-cache") - http.ServeFile(w, r, path.Join(settings.SettingsDir, settings.SettingsFile)) + if forwarder != nil { + fwd_request(w, r, *forwarder) + } else { + w.Header().Set("X-FIC-Time", fmt.Sprintf("%f", float64(time.Now().UnixNano()/1000)/1000000)) + http.ServeFile(w, r, path.Join(settings.SettingsDir, settings.SettingsFile)) + } }) api.Router().GET("/teams.json", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { w.Header().Set("Cache-Control", "no-cache") - http.ServeFile(w, r, path.Join(TeamsDir, "teams.json")) + if forwarder != nil { + fwd_request(w, r, *forwarder) + } else { + http.ServeFile(w, r, path.Join(TeamsDir, "teams.json")) + } }) api.Router().GET("/themes.json", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { w.Header().Set("Cache-Control", "no-cache") - http.ServeFile(w, r, path.Join(TeamsDir, "themes.json")) + if forwarder != nil { + fwd_request(w, r, *forwarder) + } else { + http.ServeFile(w, r, path.Join(TeamsDir, "themes.json")) + } }) api.Router().GET("/public.json", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { w.Header().Set("Cache-Control", "no-cache") - http.ServeFile(w, r, path.Join(DashboardDir, "public.json")) + if forwarder != nil && fwdPublicJson { + fwd_request(w, r, *forwarder) + } else { + http.ServeFile(w, r, path.Join(DashboardDir, "public.json")) + } }) api.Router().GET("/public0.json", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { w.Header().Set("Cache-Control", "no-cache") - http.ServeFile(w, r, path.Join(DashboardDir, "public0.json")) + if forwarder != nil && fwdPublicJson { + fwd_request(w, r, *forwarder) + } else { + http.ServeFile(w, r, path.Join(DashboardDir, "public0.json")) + } }) api.Router().GET("/public1.json", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { w.Header().Set("Cache-Control", "no-cache") - http.ServeFile(w, r, path.Join(DashboardDir, "public1.json")) + if forwarder != nil && fwdPublicJson { + fwd_request(w, r, *forwarder) + } else { + http.ServeFile(w, r, path.Join(DashboardDir, "public1.json")) + } }) api.Router().GET("/public2.json", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { w.Header().Set("Cache-Control", "no-cache") - http.ServeFile(w, r, path.Join(DashboardDir, "public2.json")) + if forwarder != nil && fwdPublicJson { + fwd_request(w, r, *forwarder) + } else { + http.ServeFile(w, r, path.Join(DashboardDir, "public2.json")) + } }) api.Router().GET("/public3.json", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { w.Header().Set("Cache-Control", "no-cache") - http.ServeFile(w, r, path.Join(DashboardDir, "public3.json")) + if forwarder != nil && fwdPublicJson { + fwd_request(w, r, *forwarder) + } else { + http.ServeFile(w, r, path.Join(DashboardDir, "public3.json")) + } }) api.Router().GET("/public4.json", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { w.Header().Set("Cache-Control", "no-cache") - http.ServeFile(w, r, path.Join(DashboardDir, "public4.json")) + if forwarder != nil && fwdPublicJson { + fwd_request(w, r, *forwarder) + } else { + http.ServeFile(w, r, path.Join(DashboardDir, "public4.json")) + } }) api.Router().GET("/public5.json", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { w.Header().Set("Cache-Control", "no-cache") - http.ServeFile(w, r, path.Join(DashboardDir, "public5.json")) + if forwarder != nil && fwdPublicJson { + fwd_request(w, r, *forwarder) + } else { + http.ServeFile(w, r, path.Join(DashboardDir, "public5.json")) + } }) api.Router().GET("/public6.json", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { w.Header().Set("Cache-Control", "no-cache") - http.ServeFile(w, r, path.Join(DashboardDir, "public6.json")) + if forwarder != nil && fwdPublicJson { + fwd_request(w, r, *forwarder) + } else { + http.ServeFile(w, r, path.Join(DashboardDir, "public6.json")) + } }) api.Router().GET("/public7.json", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { w.Header().Set("Cache-Control", "no-cache") - http.ServeFile(w, r, path.Join(DashboardDir, "public7.json")) + if forwarder != nil && fwdPublicJson { + fwd_request(w, r, *forwarder) + } else { + http.ServeFile(w, r, path.Join(DashboardDir, "public7.json")) + } }) api.Router().GET("/public8.json", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { w.Header().Set("Cache-Control", "no-cache") - http.ServeFile(w, r, path.Join(DashboardDir, "public8.json")) + if forwarder != nil && fwdPublicJson { + fwd_request(w, r, *forwarder) + } else { + http.ServeFile(w, r, path.Join(DashboardDir, "public8.json")) + } }) api.Router().GET("/public9.json", func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { w.Header().Set("Cache-Control", "no-cache") - http.ServeFile(w, r, path.Join(DashboardDir, "public9.json")) + if forwarder != nil && fwdPublicJson { + fwd_request(w, r, *forwarder) + } else { + http.ServeFile(w, r, path.Join(DashboardDir, "public9.json")) + } }) }