diff --git a/README.md b/README.md index 7ce27ad..d3f6cfc 100644 --- a/README.md +++ b/README.md @@ -344,16 +344,27 @@ mkdir REGISTRY chmod 755 REGISTRY ``` -Finally, start the Gobbler by running the binary with a few arguments, including the UIDs of administrators: +Finally, start the Gobbler by running the binary: ```sh ./gobbler \ -staging STAGING \ -registry REGISTRY \ -admin ADMIN1,ADMIN2 \ - -port PORT + -port PORT \ + -prefix PREFIX ``` -Multiple Gobbler instances can target the same `REGISTRY` with different `STAGING`. -This is useful for complex configurations where the same filesystem is mounted in multiple compute environments, -whereby a separate Gobbler instance can be set up in each environment to enable uploads. +The following optional arguments can be used to fine-tune the Gobbler's behavior: + +- `-admin` contains a comma-separated list of administrator UIDs. + This defaults to an empty strings, i.e., no administrators. +- `-port` specifies the port for API calls. + This defaults to 8080. +- `-prefix` adds an extra prefix to all endpoints, e.g., to disambiguate between versions. + For example, a prefix of `api/v2` would change the list endpoint to `/api/v2/list`. + This defaults to an empty string, i.e., no prefix. + +Multiple Gobbler instances can safely target the same `REGISTRY` with different `STAGING`. +This is useful for complex HPC configurations where the same filesystem is mounted in multiple compute environments; +a separate Gobbler instance can be set up in each environment to enable uploads. diff --git a/main.go b/main.go index 78b898c..4eeea55 100644 --- a/main.go +++ b/main.go @@ -136,10 +136,11 @@ func (a *activeRegistry) Remove(path string) { /***************************************************/ func main() { - spath := flag.String("staging", "", "Path to the staging directory.") - rpath := flag.String("registry", "", "Path to the registry.") - mstr := flag.String("admin", "", "Comma-separated list of administrators.") - port := flag.Int("port", 8080, "Port to listen to API requests.") + spath := flag.String("staging", "", "Path to the staging directory") + rpath := flag.String("registry", "", "Path to the registry") + mstr := flag.String("admin", "", "Comma-separated list of administrators (default \"\")") + port := flag.Int("port", 8080, "Port to listen to API requests") + prefix := flag.String("prefix", "", "Prefix to add to each endpoint, excluding the first and last slashes (default \"\")") flag.Parse() if *spath == "" || *rpath == "" { @@ -163,8 +164,13 @@ func main() { actreg := newActiveRegistry(11) + endpt_prefix := *prefix + if endpt_prefix != "" { + endpt_prefix = "/" + endpt_prefix + } + // Creating an endpoint to trigger jobs. - http.HandleFunc("POST /new/{path}", func(w http.ResponseWriter, r *http.Request) { + http.HandleFunc("POST " + endpt_prefix + "/new/{path}", func(w http.ResponseWriter, r *http.Request) { path := r.PathValue("path") log.Println("processing " + path) @@ -244,9 +250,10 @@ func main() { // Creating an endpoint to list and serve files, for remote access to the registry. fs := http.FileServer(http.Dir(globals.Registry)) - http.Handle("GET /fetch/", http.StripPrefix("/fetch/", fs)) + fetch_endpt := endpt_prefix + "/fetch/" + http.Handle("GET " + fetch_endpt, http.StripPrefix(fetch_endpt, fs)) - http.HandleFunc("GET /list", func(w http.ResponseWriter, r *http.Request) { + http.HandleFunc("GET " + endpt_prefix + "/list", func(w http.ResponseWriter, r *http.Request) { listing, err := listFilesHandler(r, globals.Registry) if err != nil { dumpHttpErrorResponse(w, err, "list request") @@ -255,11 +262,15 @@ func main() { } }) - // Creating a useful health-check endpoint. - http.HandleFunc("GET /info", func(w http.ResponseWriter, r *http.Request) { + // Creating some useful endpoints. + http.HandleFunc("GET " + endpt_prefix + "/info", func(w http.ResponseWriter, r *http.Request) { dumpJsonResponse(w, http.StatusOK, map[string]string{ "staging": staging, "registry": globals.Registry }, "info request") }) + http.HandleFunc("GET " + endpt_prefix + "/", func(w http.ResponseWriter, r *http.Request) { + dumpJsonResponse(w, http.StatusOK, map[string]string{ "name": "gobbler API", "url": "https://github.com/ArtifactDB/gobbler" }, "default request") + }) + // Adding a per-day job that purges various old files. ticker := time.NewTicker(time.Hour * 24) defer ticker.Stop()