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
This commit is contained in:
@@ -68,12 +68,6 @@ load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies", "go_repository")
|
|||||||
gazelle_dependencies()
|
gazelle_dependencies()
|
||||||
|
|
||||||
# Dependencies for PolyGerrit local dev server.
|
# Dependencies for PolyGerrit local dev server.
|
||||||
go_repository(
|
|
||||||
name = "com_github_robfig_soy",
|
|
||||||
commit = "82face14ebc0883b4ca9c901b5aaf3738b9f6a24",
|
|
||||||
importpath = "github.com/robfig/soy",
|
|
||||||
)
|
|
||||||
|
|
||||||
go_repository(
|
go_repository(
|
||||||
name = "com_github_howeyc_fsnotify",
|
name = "com_github_howeyc_fsnotify",
|
||||||
commit = "441bbc86b167f3c1f4786afae9931403b99fdacf",
|
commit = "441bbc86b167f3c1f4786afae9931403b99fdacf",
|
||||||
|
|||||||
@@ -57,11 +57,8 @@ go_binary(
|
|||||||
data = [
|
data = [
|
||||||
":fonts.zip",
|
":fonts.zip",
|
||||||
"//polygerrit-ui/app:test_components.zip",
|
"//polygerrit-ui/app:test_components.zip",
|
||||||
"//resources/com/google/gerrit/httpd/raw",
|
|
||||||
],
|
],
|
||||||
deps = [
|
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/httpfs:go_default_library",
|
||||||
"@org_golang_x_tools//godoc/vfs/zipfs:go_default_library",
|
"@org_golang_x_tools//godoc/vfs/zipfs:go_default_library",
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package main
|
|||||||
import (
|
import (
|
||||||
"archive/zip"
|
"archive/zip"
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"bytes"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
@@ -32,8 +33,6 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/robfig/soy"
|
|
||||||
"github.com/robfig/soy/soyhtml"
|
|
||||||
"golang.org/x/tools/godoc/vfs/httpfs"
|
"golang.org/x/tools/godoc/vfs/httpfs"
|
||||||
"golang.org/x/tools/godoc/vfs/zipfs"
|
"golang.org/x/tools/godoc/vfs/zipfs"
|
||||||
)
|
)
|
||||||
@@ -41,11 +40,9 @@ import (
|
|||||||
var (
|
var (
|
||||||
plugins = flag.String("plugins", "", "comma seperated plugin paths to serve")
|
plugins = flag.String("plugins", "", "comma seperated plugin paths to serve")
|
||||||
port = flag.String("port", ":8081", "Port to serve HTTP requests on")
|
port = flag.String("port", ":8081", "Port to serve HTTP requests on")
|
||||||
prod = flag.Bool("prod", false, "Serve production assets")
|
host = flag.String("host", "gerrit-review.googlesource.com", "Host to proxy requests to")
|
||||||
restHost = flag.String("host", "gerrit-review.googlesource.com", "Host to proxy requests to")
|
|
||||||
scheme = flag.String("scheme", "https", "URL scheme")
|
scheme = flag.String("scheme", "https", "URL scheme")
|
||||||
|
cdnPattern = regexp.MustCompile("https://cdn.googlesource.com/polygerrit_ui/[0-9.]*")
|
||||||
tofu *soyhtml.Tofu
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -61,55 +58,35 @@ func main() {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tofu, err = resolveIndexTemplate()
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
workspace := os.Getenv("BUILD_WORKSPACE_DIRECTORY")
|
workspace := os.Getenv("BUILD_WORKSPACE_DIRECTORY")
|
||||||
if err := os.Chdir(filepath.Join(workspace, "polygerrit-ui")); err != nil {
|
if err := os.Chdir(filepath.Join(workspace, "polygerrit-ui")); err != nil {
|
||||||
log.Fatal(err)
|
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.Handle("/bower_components/",
|
||||||
http.FileServer(httpfs.New(zipfs.New(componentsArchive, "bower_components"))))
|
http.FileServer(httpfs.New(zipfs.New(componentsArchive, "bower_components"))))
|
||||||
http.Handle("/fonts/",
|
http.Handle("/fonts/",
|
||||||
http.FileServer(httpfs.New(zipfs.New(fontsArchive, "fonts"))))
|
http.FileServer(httpfs.New(zipfs.New(fontsArchive, "fonts"))))
|
||||||
|
|
||||||
http.HandleFunc("/changes/", handleRESTProxy)
|
http.HandleFunc("/index.html", handleIndex)
|
||||||
http.HandleFunc("/accounts/", handleRESTProxy)
|
http.HandleFunc("/changes/", handleProxy)
|
||||||
http.HandleFunc("/config/", handleRESTProxy)
|
http.HandleFunc("/accounts/", handleProxy)
|
||||||
http.HandleFunc("/projects/", handleRESTProxy)
|
http.HandleFunc("/config/", handleProxy)
|
||||||
|
http.HandleFunc("/projects/", handleProxy)
|
||||||
http.HandleFunc("/accounts/self/detail", handleAccountDetail)
|
http.HandleFunc("/accounts/self/detail", handleAccountDetail)
|
||||||
|
|
||||||
if len(*plugins) > 0 {
|
if len(*plugins) > 0 {
|
||||||
http.Handle("/plugins/", http.StripPrefix("/plugins/",
|
http.Handle("/plugins/", http.StripPrefix("/plugins/",
|
||||||
http.FileServer(http.Dir("../plugins"))))
|
http.FileServer(http.Dir("../plugins"))))
|
||||||
log.Println("Local plugins from", "../plugins")
|
log.Println("Local plugins from", "../plugins")
|
||||||
} else {
|
} else {
|
||||||
http.HandleFunc("/plugins/", handleRESTProxy)
|
http.HandleFunc("/plugins/", handleProxy)
|
||||||
}
|
}
|
||||||
log.Println("Serving on port", *port)
|
log.Println("Serving on port", *port)
|
||||||
log.Fatal(http.ListenAndServe(*port, &server{}))
|
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) {
|
func openDataArchive(path string) (*zip.ReadCloser, error) {
|
||||||
absBinPath, err := resourceBasePath()
|
absBinPath, err := resourceBasePath()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -122,40 +99,40 @@ func resourceBasePath() (string, error) {
|
|||||||
return filepath.Abs(os.Args[0])
|
return filepath.Abs(os.Args[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleIndex(w http.ResponseWriter, r *http.Request) {
|
func handleIndex(writer http.ResponseWriter, originalRequest *http.Request) {
|
||||||
var obj = map[string]interface{}{
|
fakeRequest := &http.Request{
|
||||||
"canonicalPath": "",
|
URL: &url.URL{
|
||||||
"staticResourcePath": "",
|
Path: "/",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "text/html")
|
handleProxy(writer, fakeRequest)
|
||||||
tofu.Render(w, "com.google.gerrit.httpd.raw.Index", obj)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleRESTProxy(w http.ResponseWriter, r *http.Request) {
|
func handleProxy(writer http.ResponseWriter, originalRequest *http.Request) {
|
||||||
req := &http.Request{
|
patchedRequest := &http.Request{
|
||||||
Method: "GET",
|
Method: "GET",
|
||||||
URL: &url.URL{
|
URL: &url.URL{
|
||||||
Scheme: *scheme,
|
Scheme: *scheme,
|
||||||
Host: *restHost,
|
Host: *host,
|
||||||
Opaque: r.URL.EscapedPath(),
|
Opaque: originalRequest.URL.EscapedPath(),
|
||||||
RawQuery: r.URL.RawQuery,
|
RawQuery: originalRequest.URL.RawQuery,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
res, err := http.DefaultClient.Do(req)
|
response, err := http.DefaultClient.Do(patchedRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
http.Error(writer, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer response.Body.Close()
|
||||||
for name, values := range res.Header {
|
for name, values := range response.Header {
|
||||||
for _, value := range values {
|
for _, value := range values {
|
||||||
if name != "Content-Length" {
|
if name != "Content-Length" {
|
||||||
w.Header().Add(name, value)
|
writer.Header().Add(name, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.WriteHeader(res.StatusCode)
|
writer.WriteHeader(response.StatusCode)
|
||||||
if _, err := io.Copy(w, patchResponse(r, res)); err != nil {
|
if _, err := io.Copy(writer, patchResponse(originalRequest, response)); err != nil {
|
||||||
log.Println("Error copying response to ResponseWriter:", err)
|
log.Println("Error copying response to ResponseWriter:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -188,8 +165,10 @@ func setJsonPropByPath(json map[string]interface{}, path []string, value interfa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func patchResponse(r *http.Request, res *http.Response) io.Reader {
|
func patchResponse(req *http.Request, res *http.Response) io.Reader {
|
||||||
switch r.URL.EscapedPath() {
|
switch req.URL.EscapedPath() {
|
||||||
|
case "/":
|
||||||
|
return replaceCdn(res.Body)
|
||||||
case "/config/server/info":
|
case "/config/server/info":
|
||||||
return injectLocalPlugins(res.Body)
|
return injectLocalPlugins(res.Body)
|
||||||
default:
|
default:
|
||||||
@@ -197,13 +176,23 @@ func patchResponse(r *http.Request, res *http.Response) io.Reader {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
if len(*plugins) == 0 {
|
||||||
return r
|
return reader
|
||||||
}
|
}
|
||||||
// Skip escape prefix
|
// Skip escape prefix
|
||||||
io.CopyN(ioutil.Discard, r, 5)
|
io.CopyN(ioutil.Discard, reader, 5)
|
||||||
dec := json.NewDecoder(r)
|
dec := json.NewDecoder(reader)
|
||||||
|
|
||||||
var response map[string]interface{}
|
var response map[string]interface{}
|
||||||
err := dec.Decode(&response)
|
err := dec.Decode(&response)
|
||||||
|
|||||||
Reference in New Issue
Block a user