Add mechanism for bundling UI assets. (#153)

* Add mechanism for bundling UI assets.

The scripts/uigen.sh script will check out the UI repo, build assets,
create a static assets file, and clean up.

The dev Makefile target has been modified to run this script if no
assets file is found. There is also a build-ui target that will
unilaterally update (the dev target only builds if the file isn't found,
but doesn't update).

The handler has been updated to add the default org ID as a header if
the request path is "/".

Co-authored-by: Randall Morey <randall@randallmorey.com>
This commit is contained in:
Jeff MitchellandRandall Morey authored and GitHub committed 2020-06-30 11:26:22 -04:00
1 parent 8d8bb42418
commit 8da4effd5e
10 files changed
+147 -65

No files matched your search

+18 -24
View File
@@ -6,7 +6,6 @@ import (
"fmt"
"net/http"
"path"
"path/filepath"
"strings"
"time"
@@ -25,6 +24,7 @@ import (
"github.com/hashicorp/watchtower/internal/servers/controller/handlers/projects"
"github.com/hashicorp/watchtower/internal/servers/controller/handlers/roles"
"github.com/hashicorp/watchtower/internal/servers/controller/handlers/users"
"github.com/hashicorp/watchtower/internal/ui"
)
type HandlerProperties struct {
@@ -43,10 +43,7 @@ func (c *Controller) handler(props HandlerProperties) (http.Handler, error) {
}
mux.Handle("/v1/", h)
// TODO: enable when not in this mode, when we bundle the assets
if c.conf.RawConfig.PassthroughDirectory != "" {
mux.Handle("/", handleUi(c))
}
mux.Handle("/", handleUi(c))
corsWrappedHandler := wrapHandlerWithCors(mux, props)
commonWrappedHandler := wrapHandlerWithCommonFuncs(corsWrappedHandler, c, props)
@@ -55,13 +52,25 @@ func (c *Controller) handler(props HandlerProperties) (http.Handler, error) {
}
func handleUi(c *Controller) http.Handler {
// TODO: Do stuff with real UI data when it's bundled. We may also have to
// do a similar thing with fetching index.html in advance.
var nextHandler http.Handler
if c.conf.RawConfig.PassthroughDirectory != "" {
nextHandler = devPassthroughHandler(c)
nextHandler = ui.DevPassthroughHandler(c.logger, c.conf.RawConfig.PassthroughDirectory)
} else {
nextHandler = http.FileServer(ui.AssetFile())
}
rootHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/":
irw := newIndexResponseWriter(c.conf.DefaultOrgId)
nextHandler.ServeHTTP(irw, r)
irw.writeToWriter(w)
default:
nextHandler.ServeHTTP(w, r)
}
})
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
w.WriteHeader(http.StatusMethodNotAllowed)
@@ -95,25 +104,10 @@ func handleUi(c *Controller) http.Handler {
}
// Fall through to the next handler
nextHandler.ServeHTTP(w, r)
rootHandler.ServeHTTP(w, r)
})
}
func devPassthroughHandler(c *Controller) http.Handler {
// Panic may not be ideal but this is never a production call and it'll
// panic on startup. We could also just change the function to return
// an error.
abs, err := filepath.Abs(c.conf.RawConfig.PassthroughDirectory)
if err != nil {
panic(err)
}
c.logger.Warn("serving passthrough files at /", "path", abs)
fs := http.FileServer(http.Dir(abs))
prefixHandler := http.StripPrefix("/", fs)
return prefixHandler
}
func handleGrpcGateway(c *Controller) (http.Handler, error) {
// Register*ServiceHandlerServer methods ignore the passed in ctx. Using the baseContext now just in case this changes
// in the future, at which point we'll want to be using the baseContext.