From bd19f9075680468f44faa08fe29eef4a0edb12f7 Mon Sep 17 00:00:00 2001 From: Anbraten Date: Mon, 27 Sep 2021 00:22:23 +0200 Subject: [PATCH] Replace www-path with www-proxy option for development (#248) By adding a new ENV variable called `WOODPECKER_WWW_PROXY` it is possible to serve a webinterface via a proxy configured by the `WOODPECKER_WWW_PROXY` value for development instead of serving the interface from the bundled code or from some folder location as the old `WOODPECKER_WWW` option allowed. Using a proxy allows developing the UI with hot-reloading. --- cmd/server/flags.go | 6 +++--- cmd/server/server.go | 26 ++++++++++++++++++++++---- cmd/server/setup.go | 1 - server/router/router.go | 5 ++--- server/web/opts.go | 9 --------- server/web/opts_test.go | 8 -------- server/web/web.go | 19 ------------------- 7 files changed, 27 insertions(+), 47 deletions(-) diff --git a/cmd/server/flags.go b/cmd/server/flags.go index 01f0ca673..c97056a57 100644 --- a/cmd/server/flags.go +++ b/cmd/server/flags.go @@ -64,9 +64,9 @@ var flags = []cli.Flag{ Usage: "enable quic", }, cli.StringFlag{ - EnvVar: "DRONE_WWW,WOODPECKER_WWW", - Name: "www", - Usage: "serve the website from disk", + EnvVar: "WOODPECKER_WWW_PROXY", + Name: "www-proxy", + Usage: "serve the website by using a proxy (used for development)", Hidden: true, }, cli.StringSliceFlag{ diff --git a/cmd/server/server.go b/cmd/server/server.go index deaebd42c..0d9e8b5df 100644 --- a/cmd/server/server.go +++ b/cmd/server/server.go @@ -20,6 +20,7 @@ import ( "errors" "net" "net/http" + "net/http/httputil" "net/url" "os" "path/filepath" @@ -90,13 +91,30 @@ func loop(c *cli.Context) error { store_ := setupStore(c) setupEvilGlobals(c, store_, remote_) - // we are switching from gin to httpservermux|treemux, - // so if this code looks strange, that is why. - tree := setupTree(c) + proxyWebUI := c.String("www-proxy") + + var webUIServe func(w http.ResponseWriter, r *http.Request) + + if proxyWebUI == "" { + // we are switching from gin to httpservermux|treemux, + webUIServe = setupTree(c).ServeHTTP + } else { + origin, _ := url.Parse(proxyWebUI) + + director := func(req *http.Request) { + req.Header.Add("X-Forwarded-Host", req.Host) + req.Header.Add("X-Origin-Host", origin.Host) + req.URL.Scheme = origin.Scheme + req.URL.Host = origin.Host + } + + proxy := &httputil.ReverseProxy{Director: director} + webUIServe = proxy.ServeHTTP + } // setup the server and start the listener handler := router.Load( - tree, + webUIServe, ginrus.Ginrus(logrus.StandardLogger(), time.RFC3339, true), middleware.Version, middleware.Config(c), diff --git a/cmd/server/setup.go b/cmd/server/setup.go index b478368aa..4c801d369 100644 --- a/cmd/server/setup.go +++ b/cmd/server/setup.go @@ -209,7 +209,6 @@ func setupCoding(c *cli.Context) (remote.Remote, error) { func setupTree(c *cli.Context) *httptreemux.ContextMux { tree := httptreemux.NewContextMux() web.New( - web.WithDir(c.String("www")), web.WithSync(time.Hour*72), web.WithDocs(c.String("docs")), ).Register(tree) diff --git a/server/router/router.go b/server/router/router.go index d2da90bcb..bd3eef278 100644 --- a/server/router/router.go +++ b/server/router/router.go @@ -17,7 +17,6 @@ package router import ( "net/http" - "github.com/dimfeld/httptreemux" "github.com/gin-gonic/gin" "github.com/woodpecker-ci/woodpecker/server/api" @@ -30,7 +29,7 @@ import ( ) // Load loads the router -func Load(mux *httptreemux.ContextMux, middleware ...gin.HandlerFunc) http.Handler { +func Load(serveHTTP func(w http.ResponseWriter, r *http.Request), middleware ...gin.HandlerFunc) http.Handler { e := gin.New() e.Use(gin.Recovery()) @@ -49,7 +48,7 @@ func Load(mux *httptreemux.ContextMux, middleware ...gin.HandlerFunc) http.Handl session.User(c), ), ) - mux.ServeHTTP(c.Writer, req) + serveHTTP(c.Writer, req) }) e.GET("/logout", api.GetLogout) diff --git a/server/web/opts.go b/server/web/opts.go index 32ba6d593..aa976fa65 100644 --- a/server/web/opts.go +++ b/server/web/opts.go @@ -19,7 +19,6 @@ import "time" // Options defines website handler options. type Options struct { sync time.Duration - path string docs string } @@ -34,14 +33,6 @@ func WithSync(d time.Duration) Option { } } -// WithDir configures the website handler with the directory value -// used to serve the website from the local filesystem. -func WithDir(s string) Option { - return func(o *Options) { - o.path = s - } -} - // WithDocs configures the website handler with the documentation // website address, which should be included in the user interface. func WithDocs(s string) Option { diff --git a/server/web/opts_test.go b/server/web/opts_test.go index a217f2f02..0e676f91e 100644 --- a/server/web/opts_test.go +++ b/server/web/opts_test.go @@ -27,14 +27,6 @@ func TestWithSync(t *testing.T) { } } -func TestWithDir(t *testing.T) { - opts := new(Options) - WithDir("/tmp/www")(opts) - if got, want := opts.path, "/tmp/www"; got != want { - t.Errorf("Want www directory %q, got %q", want, got) - } -} - func TestWithDocs(t *testing.T) { opts := new(Options) WithDocs("http://docs.drone.io")(opts) diff --git a/server/web/web.go b/server/web/web.go index 9faa9e5e5..a73f81eee 100644 --- a/server/web/web.go +++ b/server/web/web.go @@ -19,9 +19,7 @@ import ( "crypto/md5" "fmt" "html/template" - "io/ioutil" "net/http" - "path/filepath" "time" "github.com/woodpecker-ci/woodpecker/model" @@ -45,10 +43,6 @@ func New(opt ...Option) Endpoint { f(opts) } - if opts.path != "" { - return fromPath(opts) - } - return &website{ fs: dist.New(), opts: opts, @@ -58,19 +52,6 @@ func New(opt ...Option) Endpoint { } } -func fromPath(opts *Options) *website { - f := filepath.Join(opts.path, "index.html") - b, err := ioutil.ReadFile(f) - if err != nil { - panic(err) - } - return &website{ - fs: http.Dir(opts.path), - tmpl: mustCreateTemplate(string(b)), - opts: opts, - } -} - type website struct { opts *Options fs http.FileSystem