From 3fc3b155626f77fc44fd0ba73c6bc754fbcb6f39 Mon Sep 17 00:00:00 2001 From: Lena Fuhrimann <6780471+cloudlena@users.noreply.github.com> Date: Thu, 9 Mar 2017 21:20:40 +0100 Subject: [PATCH] Don't use global variables --- .gitignore | 2 +- api-handlers.go => api.go | 27 ++++++++++++++------------- main.go | 7 +++++++ minio.go | 19 ++++++++++--------- page-handlers.go => pages.go | 35 ++++++++++++++++++++--------------- routes.go | 18 +++++++++++------- templates/layout.html | 4 ++-- 7 files changed, 65 insertions(+), 47 deletions(-) rename api-handlers.go => api.go (76%) rename page-handlers.go => pages.go (64%) diff --git a/.gitignore b/.gitignore index 6af0b65..543a87f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ vendor -s3manager +s3-manager glide.lock diff --git a/api-handlers.go b/api.go similarity index 76% rename from api-handlers.go rename to api.go index 99e4f4f..f8e55f9 100644 --- a/api-handlers.go +++ b/api.go @@ -18,8 +18,8 @@ type CopyObjectInfo struct { SourceObjectName string `json:"sourceObjectName"` } -// createBucketHandler creates a new bucket -func createBucketHandler(w http.ResponseWriter, r *http.Request) { +// CreateBucketHandler creates a new bucket +func (s *Server) CreateBucketHandler(w http.ResponseWriter, r *http.Request) { var bucket minio.BucketInfo err := json.NewDecoder(r.Body).Decode(&bucket) @@ -28,7 +28,7 @@ func createBucketHandler(w http.ResponseWriter, r *http.Request) { return } - err = minioClient.MakeBucket(bucket.Name, "") + err = s.s3.MakeBucket(bucket.Name, "") if err != nil { w.WriteHeader(http.StatusInternalServerError) return @@ -36,6 +36,7 @@ func createBucketHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.WriteHeader(http.StatusCreated) + err = json.NewEncoder(w).Encode(bucket) if err != nil { w.WriteHeader(http.StatusInternalServerError) @@ -44,24 +45,24 @@ func createBucketHandler(w http.ResponseWriter, r *http.Request) { } // deleteBucketHandler deletes a bucket -func deleteBucketHandler(w http.ResponseWriter, r *http.Request) { +func (s *Server) deleteBucketHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) - err := minioClient.RemoveBucket(vars["bucketName"]) + err := s.s3.RemoveBucket(vars["bucketName"]) if err != nil { w.WriteHeader(http.StatusInternalServerError) return } - w.WriteHeader(http.StatusOK) + w.WriteHeader(http.StatusNoContent) } // getObjectHandler downloads an object to the client -func getObjectHandler(w http.ResponseWriter, r *http.Request) { +func (s *Server) getObjectHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) objectName := vars["objectName"] - object, err := minioClient.GetObject(vars["bucketName"], objectName) + object, err := s.s3.GetObject(vars["bucketName"], objectName) if err != nil { w.WriteHeader(http.StatusInternalServerError) return @@ -78,7 +79,7 @@ func getObjectHandler(w http.ResponseWriter, r *http.Request) { } // createObjectHandler allows to upload a new object -func createObjectHandler(w http.ResponseWriter, r *http.Request) { +func (s *Server) createObjectHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) if r.Header.Get("Content-Type") == "application/json" { @@ -94,7 +95,7 @@ func createObjectHandler(w http.ResponseWriter, r *http.Request) { objectSource := fmt.Sprintf("/%s/%s", copy.SourceBucketName, copy.SourceObjectName) fmt.Println(copy) fmt.Println(objectSource) - err = minioClient.CopyObject(copy.BucketName, copy.ObjectName, objectSource, copyConds) + err = s.s3.CopyObject(copy.BucketName, copy.ObjectName, objectSource, copyConds) if err != nil { w.WriteHeader(http.StatusInternalServerError) return @@ -120,7 +121,7 @@ func createObjectHandler(w http.ResponseWriter, r *http.Request) { } defer file.Close() - _, err = minioClient.PutObject(vars["bucketName"], handler.Filename, file, "application/octet-stream") + _, err = s.s3.PutObject(vars["bucketName"], handler.Filename, file, "application/octet-stream") if err != nil { w.WriteHeader(http.StatusUnprocessableEntity) return @@ -131,10 +132,10 @@ func createObjectHandler(w http.ResponseWriter, r *http.Request) { } // deleteObjectHandler deletes an object -func deleteObjectHandler(w http.ResponseWriter, r *http.Request) { +func (s *Server) deleteObjectHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) - err := minioClient.RemoveObject(vars["bucketName"], vars["objectName"]) + err := s.s3.RemoveObject(vars["bucketName"], vars["objectName"]) if err != nil { w.WriteHeader(http.StatusInternalServerError) return diff --git a/main.go b/main.go index 91b51f9..8d69474 100644 --- a/main.go +++ b/main.go @@ -4,8 +4,15 @@ import ( "log" "net/http" "os" + + minio "github.com/minio/minio-go" ) +// Server is a server containing a minio client +type Server struct { + s3 *minio.Client +} + func main() { port := os.Getenv("PORT") if len(port) == 0 { diff --git a/minio.go b/minio.go index 5074acf..1baaccf 100644 --- a/minio.go +++ b/minio.go @@ -1,16 +1,15 @@ package main import ( - "log" "os" minio "github.com/minio/minio-go" ) -var minioClient *minio.Client - -func init() { +// NewMinioClient creates a new Minio client +func NewMinioClient() *minio.Client { var err error + var client *minio.Client s3Endpoint := os.Getenv("S3_ENDPOINT") if len(s3Endpoint) == 0 { @@ -19,20 +18,22 @@ func init() { s3AccessKeyID := os.Getenv("S3_ACCESS_KEY_ID") if len(s3AccessKeyID) == 0 { - log.Fatalln("Please set S3_ACCESS_KEY_ID") + panic("Please set S3_ACCESS_KEY_ID") } s3SecretAccessKey := os.Getenv("S3_SECRET_ACCESS_KEY") if len(s3SecretAccessKey) == 0 { - log.Fatalln("Please set S3_SECRET_ACCESS_KEY") + panic("Please set S3_SECRET_ACCESS_KEY") } if os.Getenv("V2_SIGNING") == "true" { - minioClient, err = minio.NewV2(s3Endpoint, s3AccessKeyID, s3SecretAccessKey, true) + client, err = minio.NewV2(s3Endpoint, s3AccessKeyID, s3SecretAccessKey, true) } else { - minioClient, err = minio.New(s3Endpoint, s3AccessKeyID, s3SecretAccessKey, true) + client, err = minio.New(s3Endpoint, s3AccessKeyID, s3SecretAccessKey, true) } if err != nil { - log.Fatalln(err) + panic(err) } + + return client } diff --git a/page-handlers.go b/pages.go similarity index 64% rename from page-handlers.go rename to pages.go index 07ce000..41aa960 100644 --- a/page-handlers.go +++ b/pages.go @@ -1,7 +1,6 @@ package main import ( - "fmt" "html/template" "net/http" "path" @@ -27,29 +26,32 @@ func indexPageHandler(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/buckets", http.StatusPermanentRedirect) } -// bucketsHandler handles the main page -func bucketsPageHandler(w http.ResponseWriter, r *http.Request) { +// bucketsPageHandler shows all buckets +func (s *Server) bucketsPageHandler(w http.ResponseWriter, r *http.Request) { lp := path.Join("templates", "layout.html") ip := path.Join("templates", "index.html") t, err := template.ParseFiles(lp, ip) if err != nil { - panic(err) + w.WriteHeader(http.StatusInternalServerError) + return } - buckets, err := minioClient.ListBuckets() + buckets, err := s.s3.ListBuckets() if err != nil { - panic(err) + w.WriteHeader(http.StatusInternalServerError) + return } err = t.ExecuteTemplate(w, "layout", buckets) if err != nil { - panic(err) + w.WriteHeader(http.StatusInternalServerError) + return } } -// bucketHandler shows the details page of a bucket -func bucketPageHandler(w http.ResponseWriter, r *http.Request) { +// bucketPageHandler shows the details page of a bucket +func (s *Server) bucketPageHandler(w http.ResponseWriter, r *http.Request) { bucketName := mux.Vars(r)["bucketName"] var objects []ObjectWithIcon @@ -58,18 +60,19 @@ func bucketPageHandler(w http.ResponseWriter, r *http.Request) { t, err := template.ParseFiles(lp, bp) if err != nil { - panic(err) + w.WriteHeader(http.StatusInternalServerError) + return } doneCh := make(chan struct{}) - objectCh := minioClient.ListObjectsV2(bucketName, "", false, doneCh) + objectCh := s.s3.ListObjectsV2(bucketName, "", false, doneCh) for object := range objectCh { if object.Err != nil { - fmt.Println(object.Err) + w.WriteHeader(http.StatusInternalServerError) return } - objectWithIcon := ObjectWithIcon{object, getIcon(object.Key)} + objectWithIcon := ObjectWithIcon{object, icon(object.Key)} objects = append(objects, objectWithIcon) } @@ -80,11 +83,13 @@ func bucketPageHandler(w http.ResponseWriter, r *http.Request) { err = t.ExecuteTemplate(w, "layout", bucketPage) if err != nil { - panic(err) + w.WriteHeader(http.StatusInternalServerError) + return } } -func getIcon(fileName string) string { +// icon returns an icon for a file type +func icon(fileName string) string { e := path.Ext(fileName) switch e { diff --git a/routes.go b/routes.go index c91f943..c4fbd7e 100644 --- a/routes.go +++ b/routes.go @@ -12,6 +12,10 @@ type Route struct { // Routes is an array of routes type Routes []Route +var s = &Server{ + s3: NewMinioClient(), +} + var routes = Routes{ Route{ "GET", @@ -21,36 +25,36 @@ var routes = Routes{ Route{ "GET", "/buckets", - Chain(bucketsPageHandler, Logger()), + Chain(s.bucketsPageHandler, Logger()), }, Route{ "GET", "/buckets/{bucketName}", - Chain(bucketPageHandler, Logger()), + Chain(s.bucketPageHandler, Logger()), }, Route{ "POST", "/api/buckets", - Chain(createBucketHandler, Logger()), + Chain(s.CreateBucketHandler, Logger()), }, Route{ "DELETE", "/api/buckets/{bucketName}", - Chain(deleteBucketHandler, Logger()), + Chain(s.deleteBucketHandler, Logger()), }, Route{ "GET", "/api/buckets/{bucketName}/objects/{objectName}", - Chain(getObjectHandler, Logger()), + Chain(s.getObjectHandler, Logger()), }, Route{ "POST", "/api/buckets/{bucketName}/objects", - Chain(createObjectHandler, Logger()), + Chain(s.createObjectHandler, Logger()), }, Route{ "DELETE", "/api/buckets/{bucketName}/objects/{objectName}", - Chain(deleteObjectHandler, Logger()), + Chain(s.deleteObjectHandler, Logger()), }, } diff --git a/templates/layout.html b/templates/layout.html index 3ec7004..f72b496 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -10,7 +10,7 @@ S3 Manager - + @@ -18,7 +18,7 @@ {{ template "content" . }} - +