Fix the PolyGerrit run-server.sh script

The go soy parser is not able to handle newer syntax changes and was
deemed to not be worth fixing. So this change removes the dependency
on the go soy parser by instead patching the server response when it
comes back.

Also removes that unused "prod" flag, which allowed pointing to a dist
directory that does not exist anymore.

Also renames some variables in the server.go script.

Tested by checking that tests are run and the proxy is usable:
http://localhost:8081/
http://localhost:8081/elements/core/gr-search-bar/gr-search-bar_test.html

Bug: Issue 10579
Change-Id: I1d2a155e93c9eb42ff72bfa56819f44a266f8fc5
diff --git a/WORKSPACE b/WORKSPACE
index b4b1a64..38122f7 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -69,12 +69,6 @@
 
 # Dependencies for PolyGerrit local dev server.
 go_repository(
-    name = "com_github_robfig_soy",
-    commit = "82face14ebc0883b4ca9c901b5aaf3738b9f6a24",
-    importpath = "github.com/robfig/soy",
-)
-
-go_repository(
     name = "com_github_howeyc_fsnotify",
     commit = "441bbc86b167f3c1f4786afae9931403b99fdacf",
     importpath = "github.com/howeyc/fsnotify",
diff --git a/polygerrit-ui/BUILD b/polygerrit-ui/BUILD
index 3988f95..0e9b4bb 100644
--- a/polygerrit-ui/BUILD
+++ b/polygerrit-ui/BUILD
@@ -57,11 +57,8 @@
     data = [
         ":fonts.zip",
         "//polygerrit-ui/app:test_components.zip",
-        "//resources/com/google/gerrit/httpd/raw",
     ],
     deps = [
-        "@com_github_robfig_soy//:go_default_library",
-        "@com_github_robfig_soy//soyhtml:go_default_library",
         "@org_golang_x_tools//godoc/vfs/httpfs:go_default_library",
         "@org_golang_x_tools//godoc/vfs/zipfs:go_default_library",
     ],
diff --git a/polygerrit-ui/server.go b/polygerrit-ui/server.go
index ba685184..2f5df90 100644
--- a/polygerrit-ui/server.go
+++ b/polygerrit-ui/server.go
@@ -17,6 +17,7 @@
 import (
 	"archive/zip"
 	"bufio"
+	"bytes"
 	"compress/gzip"
 	"encoding/json"
 	"errors"
@@ -32,20 +33,16 @@
 	"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 (
-	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")
-
-	tofu *soyhtml.Tofu
+	plugins    = flag.String("plugins", "", "comma seperated plugin paths to serve")
+	port       = flag.String("port", ":8081", "Port to serve HTTP requests on")
+	host       = flag.String("host", "gerrit-review.googlesource.com", "Host to proxy requests to")
+	scheme     = flag.String("scheme", "https", "URL scheme")
+	cdnPattern = regexp.MustCompile("https://cdn.googlesource.com/polygerrit_ui/[0-9.]*")
 )
 
 func main() {
@@ -61,55 +58,35 @@
 		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("/", 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)
-	http.HandleFunc("/projects/", handleRESTProxy)
+	http.HandleFunc("/index.html", handleIndex)
+	http.HandleFunc("/changes/", handleProxy)
+	http.HandleFunc("/accounts/", handleProxy)
+	http.HandleFunc("/config/", handleProxy)
+	http.HandleFunc("/projects/", handleProxy)
 	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")
 	} else {
-		http.HandleFunc("/plugins/", handleRESTProxy)
+		http.HandleFunc("/plugins/", handleProxy)
 	}
 	log.Println("Serving on port", *port)
 	log.Fatal(http.ListenAndServe(*port, &server{}))
 }
 
-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 {
@@ -122,40 +99,40 @@
 	return filepath.Abs(os.Args[0])
 }
 
-func handleIndex(w http.ResponseWriter, r *http.Request) {
-	var obj = map[string]interface{}{
-		"canonicalPath":      "",
-		"staticResourcePath": "",
+func handleIndex(writer http.ResponseWriter, originalRequest *http.Request) {
+	fakeRequest := &http.Request{
+		URL: &url.URL{
+			Path: "/",
+		},
 	}
-	w.Header().Set("Content-Type", "text/html")
-	tofu.Render(w, "com.google.gerrit.httpd.raw.Index", obj)
+	handleProxy(writer, fakeRequest)
 }
 
-func handleRESTProxy(w http.ResponseWriter, r *http.Request) {
-	req := &http.Request{
+func handleProxy(writer http.ResponseWriter, originalRequest *http.Request) {
+	patchedRequest := &http.Request{
 		Method: "GET",
 		URL: &url.URL{
 			Scheme:   *scheme,
-			Host:     *restHost,
-			Opaque:   r.URL.EscapedPath(),
-			RawQuery: r.URL.RawQuery,
+			Host:     *host,
+			Opaque:   originalRequest.URL.EscapedPath(),
+			RawQuery: originalRequest.URL.RawQuery,
 		},
 	}
-	res, err := http.DefaultClient.Do(req)
+	response, err := http.DefaultClient.Do(patchedRequest)
 	if err != nil {
-		http.Error(w, err.Error(), http.StatusInternalServerError)
+		http.Error(writer, err.Error(), http.StatusInternalServerError)
 		return
 	}
-	defer res.Body.Close()
-	for name, values := range res.Header {
+	defer response.Body.Close()
+	for name, values := range response.Header {
 		for _, value := range values {
 			if name != "Content-Length" {
-				w.Header().Add(name, value)
+				writer.Header().Add(name, value)
 			}
 		}
 	}
-	w.WriteHeader(res.StatusCode)
-	if _, err := io.Copy(w, patchResponse(r, res)); err != nil {
+	writer.WriteHeader(response.StatusCode)
+	if _, err := io.Copy(writer, patchResponse(originalRequest, response)); err != nil {
 		log.Println("Error copying response to ResponseWriter:", err)
 		return
 	}
@@ -188,8 +165,10 @@
 	}
 }
 
-func patchResponse(r *http.Request, res *http.Response) io.Reader {
-	switch r.URL.EscapedPath() {
+func patchResponse(req *http.Request, res *http.Response) io.Reader {
+	switch req.URL.EscapedPath() {
+	case "/":
+		return replaceCdn(res.Body)
 	case "/config/server/info":
 		return injectLocalPlugins(res.Body)
 	default:
@@ -197,13 +176,23 @@
 	}
 }
 
-func injectLocalPlugins(r io.Reader) io.Reader {
+func replaceCdn(reader io.Reader) io.Reader {
+	buf := new(bytes.Buffer)
+	buf.ReadFrom(reader)
+	original := buf.String()
+
+	replaced := cdnPattern.ReplaceAllString(original, "")
+
+	return strings.NewReader(replaced)
+}
+
+func injectLocalPlugins(reader io.Reader) io.Reader {
 	if len(*plugins) == 0 {
-		return r
+		return reader
 	}
 	// Skip escape prefix
-	io.CopyN(ioutil.Discard, r, 5)
-	dec := json.NewDecoder(r)
+	io.CopyN(ioutil.Discard, reader, 5)
+	dec := json.NewDecoder(reader)
 
 	var response map[string]interface{}
 	err := dec.Decode(&response)