diff options
Diffstat (limited to 'polygerrit-ui/server.go')
-rw-r--r-- | polygerrit-ui/server.go | 126 |
1 files changed, 99 insertions, 27 deletions
diff --git a/polygerrit-ui/server.go b/polygerrit-ui/server.go index 79cf4bf55d..ba685184e8 100644 --- a/polygerrit-ui/server.go +++ b/polygerrit-ui/server.go @@ -15,6 +15,7 @@ package main import ( + "archive/zip" "bufio" "compress/gzip" "encoding/json" @@ -26,27 +27,63 @@ import ( "net" "net/http" "net/url" + "os" + "path/filepath" "regexp" "strings" + + "github.com/robfig/soy" + "github.com/robfig/soy/soyhtml" + "golang.org/x/tools/godoc/vfs/httpfs" + "golang.org/x/tools/godoc/vfs/zipfs" ) var ( - restHost = flag.String("host", "gerrit-review.googlesource.com", "Host to proxy requests to") + plugins = flag.String("plugins", "", "comma seperated plugin paths to serve") port = flag.String("port", ":8081", "Port to serve HTTP requests on") prod = flag.Bool("prod", false, "Serve production assets") + restHost = flag.String("host", "gerrit-review.googlesource.com", "Host to proxy requests to") scheme = flag.String("scheme", "https", "URL scheme") - plugins = flag.String("plugins", "", "Path to local plugins folder") + + tofu *soyhtml.Tofu ) func main() { flag.Parse() + fontsArchive, err := openDataArchive("fonts.zip") + if err != nil { + log.Fatal(err) + } + + componentsArchive, err := openDataArchive("app/test_components.zip") + if err != nil { + log.Fatal(err) + } + + tofu, err = resolveIndexTemplate() + if err != nil { + log.Fatal(err) + } + + workspace := os.Getenv("BUILD_WORKSPACE_DIRECTORY") + if err := os.Chdir(filepath.Join(workspace, "polygerrit-ui")); err != nil { + log.Fatal(err) + } + + http.HandleFunc("/index.html", handleIndex) + if *prod { http.Handle("/", http.FileServer(http.Dir("dist"))) } else { http.Handle("/", http.FileServer(http.Dir("app"))) } + http.Handle("/bower_components/", + http.FileServer(httpfs.New(zipfs.New(componentsArchive, "bower_components")))) + http.Handle("/fonts/", + http.FileServer(httpfs.New(zipfs.New(fontsArchive, "fonts")))) + http.HandleFunc("/changes/", handleRESTProxy) http.HandleFunc("/accounts/", handleRESTProxy) http.HandleFunc("/config/", handleRESTProxy) @@ -54,8 +91,8 @@ func main() { http.HandleFunc("/accounts/self/detail", handleAccountDetail) if len(*plugins) > 0 { http.Handle("/plugins/", http.StripPrefix("/plugins/", - http.FileServer(http.Dir(*plugins)))) - log.Println("Local plugins from", *plugins) + http.FileServer(http.Dir("../plugins")))) + log.Println("Local plugins from", "../plugins") } else { http.HandleFunc("/plugins/", handleRESTProxy) } @@ -63,14 +100,38 @@ func main() { log.Fatal(http.ListenAndServe(*port, &server{})) } -func handleRESTProxy(w http.ResponseWriter, r *http.Request) { - if strings.HasSuffix(r.URL.Path, ".html") { - w.Header().Set("Content-Type", "text/html") - } else if strings.HasSuffix(r.URL.Path, ".css") { - w.Header().Set("Content-Type", "text/css") - } else { - w.Header().Set("Content-Type", "application/json") +func resolveIndexTemplate() (*soyhtml.Tofu, error) { + basePath, err := resourceBasePath() + if err != nil { + return nil, err + } + return soy.NewBundle(). + AddTemplateFile(basePath + ".runfiles/gerrit/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy"). + CompileToTofu() +} + +func openDataArchive(path string) (*zip.ReadCloser, error) { + absBinPath, err := resourceBasePath() + if err != nil { + return nil, err + } + return zip.OpenReader(absBinPath + ".runfiles/gerrit/polygerrit-ui/" + path) +} + +func resourceBasePath() (string, error) { + return filepath.Abs(os.Args[0]) +} + +func handleIndex(w http.ResponseWriter, r *http.Request) { + var obj = map[string]interface{}{ + "canonicalPath": "", + "staticResourcePath": "", } + w.Header().Set("Content-Type", "text/html") + tofu.Render(w, "com.google.gerrit.httpd.raw.Index", obj) +} + +func handleRESTProxy(w http.ResponseWriter, r *http.Request) { req := &http.Request{ Method: "GET", URL: &url.URL{ @@ -86,6 +147,13 @@ func handleRESTProxy(w http.ResponseWriter, r *http.Request) { return } defer res.Body.Close() + for name, values := range res.Header { + for _, value := range values { + if name != "Content-Length" { + w.Header().Add(name, value) + } + } + } w.WriteHeader(res.StatusCode) if _, err := io.Copy(w, patchResponse(r, res)); err != nil { log.Println("Error copying response to ResponseWriter:", err) @@ -144,19 +212,23 @@ func injectLocalPlugins(r io.Reader) io.Reader { } // Configuration path in the JSON server response - pluginsPath := []string{"plugin", "html_resource_paths"} + jsPluginsPath := []string{"plugin", "js_resource_paths"} + htmlPluginsPath := []string{"plugin", "html_resource_paths"} + htmlResources := getJsonPropByPath(response, htmlPluginsPath).([]interface{}) + jsResources := getJsonPropByPath(response, jsPluginsPath).([]interface{}) - htmlResources := getJsonPropByPath(response, pluginsPath).([]interface{}) - files, err := ioutil.ReadDir(*plugins) - if err != nil { - log.Fatal(err) - } - for _, f := range files { - if strings.HasSuffix(f.Name(), ".html") { - htmlResources = append(htmlResources, "plugins/"+f.Name()) + for _, p := range strings.Split(*plugins, ",") { + if strings.HasSuffix(p, ".html") { + htmlResources = append(htmlResources, p) + } + + if strings.HasSuffix(p, ".js") { + jsResources = append(jsResources, p) } } - setJsonPropByPath(response, pluginsPath, htmlResources) + + setJsonPropByPath(response, jsPluginsPath, jsResources) + setJsonPropByPath(response, htmlPluginsPath, htmlResources) reader, writer := io.Pipe() go func() { @@ -200,20 +272,20 @@ type server struct{} // Any path prefixes that should resolve to index.html. var ( - fePaths = []string{"/q/", "/c/", "/dashboard/", "/admin/"} + fePaths = []string{"/q/", "/c/", "/p/", "/x/", "/dashboard/", "/admin/"} issueNumRE = regexp.MustCompile(`^\/\d+\/?$`) ) func (_ *server) ServeHTTP(w http.ResponseWriter, r *http.Request) { log.Printf("%s %s %s %s\n", r.Proto, r.Method, r.RemoteAddr, r.URL) for _, prefix := range fePaths { - if strings.HasPrefix(r.URL.Path, prefix) { - r.URL.Path = "/" - log.Println("Redirecting to /") + if strings.HasPrefix(r.URL.Path, prefix) || r.URL.Path == "/" { + r.URL.Path = "/index.html" + log.Println("Redirecting to /index.html") break } else if match := issueNumRE.Find([]byte(r.URL.Path)); match != nil { - r.URL.Path = "/" - log.Println("Redirecting to /") + r.URL.Path = "/index.html" + log.Println("Redirecting to /index.html") break } } |