add request for asset names for skotties

http request is formatted as [endpoint]/_/r/[hash]

it returns as a json:
{"files":["asset1.png","asset2.png"]}

Change-Id: Iee8a797f040c76607c5b7051442969271537f56f
Reviewed-on: https://skia-review.googlesource.com/c/buildbot/+/777220
Reviewed-by: Kevin Lubick <kjlubick@google.com>
Commit-Queue: Jorge Betancourt <jmbetancourt@google.com>
diff --git a/skottie/go/skottie/BUILD.bazel b/skottie/go/skottie/BUILD.bazel
index b6565fc..fbe87c1 100644
--- a/skottie/go/skottie/BUILD.bazel
+++ b/skottie/go/skottie/BUILD.bazel
@@ -24,12 +24,6 @@
     ],
 )
 
-go_binary(
-    name = "skottie",
-    embed = [":skottie_lib"],
-    visibility = ["//visibility:public"],
-)
-
 go_test(
     name = "skottie_test",
     srcs = ["skottie_test.go"],
@@ -45,3 +39,9 @@
         "@com_github_stretchr_testify//require",
     ],
 )
+
+go_binary(
+    name = "skottie",
+    embed = [":skottie_lib"],
+    visibility = ["//visibility:public"],
+)
diff --git a/skottie/go/skottie/skottie.go b/skottie/go/skottie/skottie.go
index 4b81a3d..8605f65 100644
--- a/skottie/go/skottie/skottie.go
+++ b/skottie/go/skottie/skottie.go
@@ -13,6 +13,7 @@
 	"io"
 	"mime"
 	"net/http"
+	"path"
 	"path/filepath"
 	"regexp"
 	"runtime"
@@ -103,6 +104,7 @@
 
 	r.Get("/_/j/{hash:[0-9A-Za-z]+}", srv.jsonHandler)
 	r.Get(`/_/a/{hash:[0-9A-Za-z]+}/{name:[A-Za-z0-9\._\-]+}`, srv.assetsHandler)
+	r.Get("/_/r/{hash:[0-9A-Za-z]+}", srv.resourceListHandler)
 	r.Post("/_/upload", srv.uploadHandler)
 
 	r.Get("/static/*", http.StripPrefix("/static/", http.HandlerFunc(httputils.CorsHandler(resourceHandler(sc.ResourcesPath)))).ServeHTTP)
@@ -258,6 +260,35 @@
 	}
 }
 
+// list handler expects a URL as follows:
+// [endpoint]/[hash]
+// It then looks in the GCS location:
+// gs://[bucket]/[hash]/assets/
+// and prints the available names to the writer
+func (s *Server) resourceListHandler(w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set("Access-Control-Allow-Origin", "*")
+	hash := chi.URLParam(r, "hash")
+	directory := strings.Join([]string{hash, "assets"}, "/")
+	var fileNames []string
+	err := s.gcsClient.AllFilesInDirectory(r.Context(), directory,
+		func(item *storage.ObjectAttrs) error {
+			fileNames = append(fileNames, path.Base(item.Name))
+			return nil
+		})
+	resp := ResourceListResponse{
+		Files: fileNames,
+	}
+	if err != nil {
+		http.Error(w, "Can't find asset directory", http.StatusNotFound)
+		return
+	}
+	if err := json.NewEncoder(w).Encode(resp); err != nil {
+		httputils.ReportError(w, err, "Failed to write JSON file.", http.StatusInternalServerError)
+		return
+	}
+}
+
 type UploadRequest struct {
 	Lottie   interface{} `json:"lottie"` // the parsed JSON
 	Filename string      `json:"filename"`
@@ -274,6 +305,10 @@
 	AssetsFilename string `json:"assetsFilename"`
 }
 
+type ResourceListResponse struct {
+	Files []string `json:"files"`
+}
+
 type UploadResponse struct {
 	Hash   string      `json:"hash"`
 	Lottie interface{} `json:"lottie"` // the parsed JSON