From 7b75be21e127e3afac4253598ae5e4cf2d8147f5 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Wed, 15 Nov 2017 19:06:53 +0100 Subject: [PATCH] refactored main code --- handlers/auth.go | 3 +-- handlers/auth_test.go | 3 ++- handlers/handlers.go | 7 +++++-- handlers/public.go | 15 ++++++++++++--- handlers/public_test.go | 10 +++++----- handlers/utils.go | 15 --------------- main.go | 2 +- store/store.go | 11 +++++------ store/util.go | 23 +++++++++-------------- util/config.go | 10 ++++------ util/private.go | 18 +++++++++--------- 11 files changed, 53 insertions(+), 64 deletions(-) delete mode 100644 handlers/utils.go diff --git a/handlers/auth.go b/handlers/auth.go index fd8050f..a26fd97 100644 --- a/handlers/auth.go +++ b/handlers/auth.go @@ -1,7 +1,6 @@ package handlers import ( - "fmt" "net/http" "github.com/maxibanki/golang-url-shortener/handlers/auth" @@ -28,7 +27,7 @@ func (h *Handler) parseJWT(wt string) (*auth.JWTClaims, error) { return util.GetPrivateKey(), nil }) if err != nil { - return nil, fmt.Errorf("could not parse token: %v", err) + return nil, errors.Wrap(err, "could not parse token") } if !token.Valid { return nil, errors.New("token is not valid") diff --git a/handlers/auth_test.go b/handlers/auth_test.go index 1e9ef85..c9c2f69 100644 --- a/handlers/auth_test.go +++ b/handlers/auth_test.go @@ -45,7 +45,8 @@ func TestCreateBackend(t *testing.T) { if err != nil { t.Fatalf("could not create store: %v", err) } - handler, err := New(*store, true) + DoNotPrivateKeyChecking = true + handler, err := New(*store) if err != nil { t.Fatalf("could not create handler: %v", err) } diff --git a/handlers/handlers.go b/handlers/handlers.go index 7aa1b91..dabd6e4 100644 --- a/handlers/handlers.go +++ b/handlers/handlers.go @@ -24,8 +24,11 @@ type Handler struct { engine *gin.Engine } +// DoNotPrivateKeyChecking is used for testing +var DoNotPrivateKeyChecking = false + // New initializes the http handlers -func New(store store.Store, testing bool) (*Handler, error) { +func New(store store.Store) (*Handler, error) { if !viper.GetBool("General.EnableDebugMode") { gin.SetMode(gin.ReleaseMode) } @@ -36,7 +39,7 @@ func New(store store.Store, testing bool) (*Handler, error) { if err := h.setHandlers(); err != nil { return nil, errors.Wrap(err, "could not set handlers") } - if !testing { + if !DoNotPrivateKeyChecking { if err := util.CheckForPrivateKey(); err != nil { return nil, errors.Wrap(err, "could not check for privat key") } diff --git a/handlers/public.go b/handlers/public.go index 9545463..858730c 100644 --- a/handlers/public.go +++ b/handlers/public.go @@ -1,6 +1,7 @@ package handlers import ( + "fmt" "net/http" "github.com/gin-gonic/gin" @@ -8,9 +9,9 @@ import ( "github.com/maxibanki/golang-url-shortener/store" ) -// URLUtil is used to help in- and outgoing requests for json +// urlUtil is used to help in- and outgoing requests for json // un- and marshalling -type URLUtil struct { +type urlUtil struct { URL string `binding:"required"` ID string } @@ -63,7 +64,7 @@ func (h *Handler) handleAccess(c *gin.Context) { // handleCreate handles requests to create an entry func (h *Handler) handleCreate(c *gin.Context) { - var data URLUtil + var data urlUtil if err := c.ShouldBind(&data); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return @@ -84,3 +85,11 @@ func (h *Handler) handleCreate(c *gin.Context) { data.URL = h.getSchemaAndHost(c) + "/" + id c.JSON(http.StatusOK, data) } + +func (h *Handler) getSchemaAndHost(c *gin.Context) string { + protocol := "http" + if c.Request.TLS != nil { + protocol = "https" + } + return fmt.Sprintf("%s://%s", protocol, c.Request.Host) +} diff --git a/handlers/public_test.go b/handlers/public_test.go index 72fc268..98584cf 100644 --- a/handlers/public_test.go +++ b/handlers/public_test.go @@ -25,7 +25,7 @@ func TestCreateEntry(t *testing.T) { ignoreResponse bool contentType string response gin.H - requestBody URLUtil + requestBody urlUtil statusCode int }{ { @@ -37,7 +37,7 @@ func TestCreateEntry(t *testing.T) { }, { name: "short URL generation", - requestBody: URLUtil{ + requestBody: urlUtil{ URL: "https://www.google.de/", }, statusCode: http.StatusOK, @@ -45,7 +45,7 @@ func TestCreateEntry(t *testing.T) { }, { name: "no valid URL", - requestBody: URLUtil{ + requestBody: urlUtil{ URL: "this is really not a URL", }, statusCode: http.StatusBadRequest, @@ -76,7 +76,7 @@ func TestCreateEntry(t *testing.T) { if tc.ignoreResponse { return } - var parsed URLUtil + var parsed urlUtil if err := json.Unmarshal(respBody, &parsed); err != nil { t.Fatalf("could not unmarshal data: %v", err) } @@ -96,7 +96,7 @@ func TestHandleInfo(t *testing.T) { t.Fatalf("could not marshal json: %v", err) } respBody := createEntryWithJSON(t, reqBody, "application/json; charset=utf-8", http.StatusOK) - var parsed URLUtil + var parsed urlUtil if err = json.Unmarshal(respBody, &parsed); err != nil { t.Fatalf("could not unmarshal data: %v", err) } diff --git a/handlers/utils.go b/handlers/utils.go deleted file mode 100644 index c23fcf0..0000000 --- a/handlers/utils.go +++ /dev/null @@ -1,15 +0,0 @@ -package handlers - -import ( - "fmt" - - "github.com/gin-gonic/gin" -) - -func (h *Handler) getSchemaAndHost(c *gin.Context) string { - protocol := "http" - if c.Request.TLS != nil { - protocol = "https" - } - return fmt.Sprintf("%s://%s", protocol, c.Request.Host) -} diff --git a/main.go b/main.go index 8a62d58..c79447f 100644 --- a/main.go +++ b/main.go @@ -41,7 +41,7 @@ func initShortener() (func(), error) { if err != nil { return nil, errors.Wrap(err, "could not create store") } - handler, err := handlers.New(*store, false) + handler, err := handlers.New(*store) if err != nil { return nil, errors.Wrap(err, "could not create handlers") } diff --git a/store/store.go b/store/store.go index e48f6c4..517c2fc 100644 --- a/store/store.go +++ b/store/store.go @@ -29,6 +29,7 @@ type Entry struct { Public EntryPublicData } +// EntryPublicData is the public part of an entry type EntryPublicData struct { CreatedOn, LastVisit time.Time VisitCount int @@ -73,12 +74,12 @@ func (s *Store) GetEntryByID(id string) (*Entry, error) { if id == "" { return nil, ErrIDIsEmpty } - raw, err := s.GetEntryByIDRaw(id) + rawEntry, err := s.GetEntryByIDRaw(id) if err != nil { return nil, err } var entry *Entry - return entry, json.Unmarshal(raw, &entry) + return entry, json.Unmarshal(rawEntry, &entry) } // IncreaseVisitCounter increments the visit counter of an entry @@ -93,26 +94,24 @@ func (s *Store) IncreaseVisitCounter(id string) error { if err != nil { return err } - err = s.db.Update(func(tx *bolt.Tx) error { + return s.db.Update(func(tx *bolt.Tx) error { if err := tx.Bucket(s.bucketName).Put([]byte(id), raw); err != nil { return errors.Wrap(err, "could not put updated visitor count JSON into the bucket") } return nil }) - return err } // GetEntryByIDRaw returns the raw data (JSON) of a data set func (s *Store) GetEntryByIDRaw(id string) ([]byte, error) { var raw []byte - err := s.db.View(func(tx *bolt.Tx) error { + return raw, s.db.View(func(tx *bolt.Tx) error { raw = tx.Bucket(s.bucketName).Get([]byte(id)) if raw == nil { return ErrNoEntryFound } return nil }) - return raw, err } // CreateEntry creates a new record and returns his short id diff --git a/store/util.go b/store/util.go index 2d00b33..bbda0a3 100644 --- a/store/util.go +++ b/store/util.go @@ -13,10 +13,9 @@ import ( // createEntryRaw creates a entry with the given key value pair func (s *Store) createEntryRaw(key, value []byte) error { - err := s.db.Update(func(tx *bolt.Tx) error { + return s.db.Update(func(tx *bolt.Tx) error { bucket := tx.Bucket(s.bucketName) - raw := bucket.Get(key) - if raw != nil { + if raw := bucket.Get(key); raw != nil { return errors.New("entry already exists") } if err := bucket.Put(key, value); err != nil { @@ -24,27 +23,23 @@ func (s *Store) createEntryRaw(key, value []byte) error { } return nil }) - return err } -// createEntry creates a new entry -func (s *Store) createEntry(entry Entry, givenID string) (string, error) { - var id string +// createEntry creates a new entry with a randomly generated id. If on is present +// then the given ID is used +func (s *Store) createEntry(entry Entry, entryID string) (string, error) { var err error - if givenID != "" { - id = givenID - } else { - id, err = generateRandomString(s.idLength) - if err != nil { + if entryID == "" { + if entryID, err = generateRandomString(s.idLength); err != nil { return "", errors.Wrap(err, "could not generate random string") } } entry.Public.CreatedOn = time.Now() - raw, err := json.Marshal(entry) + rawEntry, err := json.Marshal(entry) if err != nil { return "", err } - return id, s.createEntryRaw([]byte(id), raw) + return entryID, s.createEntryRaw([]byte(entryID), rawEntry) } // generateRandomString generates a random string with an predefined length diff --git a/util/config.go b/util/config.go index 3a982ee..5199fe8 100644 --- a/util/config.go +++ b/util/config.go @@ -11,8 +11,8 @@ import ( var ( dataDirPath string - // DoNotSetConfigName is used to predefine if the ConfigName should be set. - // used for the unit testing reason + // DoNotSetConfigName is used to predefine if the name of the config should be set. + // Used for the unit testing DoNotSetConfigName = false ) @@ -26,8 +26,7 @@ func ReadInConfig() error { } viper.AddConfigPath(".") setConfigDefaults() - err := viper.ReadInConfig() - if err != nil { + if err := viper.ReadInConfig(); err != nil { return errors.Wrap(err, "could not reload config file") } return checkForDatadir() @@ -56,8 +55,7 @@ func checkForDatadir() error { return errors.Wrap(err, "could not get relative data dir path") } if _, err = os.Stat(dataDirPath); os.IsNotExist(err) { - err = os.MkdirAll(dataDirPath, 0755) - if err != nil { + if err = os.MkdirAll(dataDirPath, 0755); err != nil { return errors.Wrap(err, "could not create config directory") } } diff --git a/util/private.go b/util/private.go index 96d3d79..1f7d4ef 100644 --- a/util/private.go +++ b/util/private.go @@ -11,28 +11,28 @@ import ( var privateKey []byte -// CheckForPrivateKey checks if already an private key exists, if not one will be randomly generated +// CheckForPrivateKey checks if already an private key exists, if not it will be randomly generated func CheckForPrivateKey() error { - privateDat := filepath.Join(GetDataDir(), "private.dat") - d, err := ioutil.ReadFile(privateDat) + privateDatPath := filepath.Join(GetDataDir(), "private.dat") + privateDatContent, err := ioutil.ReadFile(privateDatPath) if err == nil { - privateKey = d + privateKey = privateDatContent } else if os.IsNotExist(err) { - b := make([]byte, 256) - if _, err := rand.Read(b); err != nil { + randomGeneratedKey := make([]byte, 256) + if _, err := rand.Read(randomGeneratedKey); err != nil { return errors.Wrap(err, "could not read random bytes") } - if err = ioutil.WriteFile(privateDat, b, 0644); err != nil { + if err = ioutil.WriteFile(privateDatPath, randomGeneratedKey, 0644); err != nil { return errors.Wrap(err, "could not write private key") } - privateKey = b + privateKey = randomGeneratedKey } else if err != nil { return errors.Wrap(err, "could not read private key") } return nil } -// GetPrivateKey returns the private key from the memory +// GetPrivateKey returns the private key from the loaded private key func GetPrivateKey() []byte { return privateKey }