4
0

singleFrontend.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package httpservers
  2. /*
  3. This file implements a very simple, lightweight reverse proxy so that REST and
  4. the webui can be accessed from a single endpoint.
  5. This makes external reverse proxies (treafik, haproxy, etc) easier, CORS goes
  6. away, and several other issues.
  7. */
  8. import (
  9. "net/http"
  10. "net/http/httputil"
  11. "net/url"
  12. config "github.com/OliveTin/OliveTin/internal/config"
  13. log "github.com/sirupsen/logrus"
  14. )
  15. func logDebugRequest(cfg *config.Config, source string, r *http.Request) {
  16. if cfg.LogDebugOptions.SingleFrontendRequests {
  17. log.Debugf("SingleFrontend HTTP Req URL %v: %q", source, r.URL)
  18. if cfg.LogDebugOptions.SingleFrontendRequestHeaders {
  19. for name, values := range r.Header {
  20. log.Debugf("SingleFrontend HTTP Req Hdr: %v = %v", name, values)
  21. }
  22. }
  23. }
  24. }
  25. // StartSingleHTTPFrontend will create a reverse proxy that proxies the API
  26. // and webui internally.
  27. func StartSingleHTTPFrontend(cfg *config.Config) {
  28. log.WithFields(log.Fields{
  29. "address": cfg.ListenAddressSingleHTTPFrontend,
  30. }).Info("Starting single HTTP frontend")
  31. apiURL, _ := url.Parse("http://" + cfg.ListenAddressRestActions)
  32. apiProxy := httputil.NewSingleHostReverseProxy(apiURL)
  33. webuiURL, _ := url.Parse("http://" + cfg.ListenAddressWebUI)
  34. webuiProxy := httputil.NewSingleHostReverseProxy(webuiURL)
  35. mux := http.NewServeMux()
  36. mux.HandleFunc("/api/", func(w http.ResponseWriter, r *http.Request) {
  37. logDebugRequest(cfg, "api ", r)
  38. apiProxy.ServeHTTP(w, r)
  39. })
  40. mux.HandleFunc("/websocket", func(w http.ResponseWriter, r *http.Request) {
  41. logDebugRequest(cfg, "ws ", r)
  42. handleWebsocket(w, r)
  43. })
  44. mux.HandleFunc("/oauth/login", handleOAuthLogin)
  45. mux.HandleFunc("/oauth/callback", handleOAuthCallback)
  46. mux.HandleFunc("/readyz", handleReadyz)
  47. mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
  48. logDebugRequest(cfg, "ui ", r)
  49. webuiProxy.ServeHTTP(w, r)
  50. })
  51. if cfg.Prometheus.Enabled {
  52. promURL, _ := url.Parse("http://" + cfg.ListenAddressPrometheus)
  53. promProxy := httputil.NewSingleHostReverseProxy(promURL)
  54. mux.HandleFunc("/metrics", func(w http.ResponseWriter, r *http.Request) {
  55. logDebugRequest(cfg, "prom", r)
  56. promProxy.ServeHTTP(w, r)
  57. })
  58. }
  59. oauth2Init(cfg)
  60. srv := &http.Server{
  61. Addr: cfg.ListenAddressSingleHTTPFrontend,
  62. Handler: mux,
  63. }
  64. log.Fatal(srv.ListenAndServe())
  65. }
  66. func handleReadyz(w http.ResponseWriter, r *http.Request) {
  67. w.Header().Set("Content-Type", "text/plain; charset=utf-8")
  68. w.WriteHeader(http.StatusOK)
  69. w.Write([]byte("OK. Single HTTP Frontend is ready.\n"))
  70. }