diff --git a/README.md b/README.md index 02de5e2..1dc93ef 100644 --- a/README.md +++ b/README.md @@ -116,9 +116,10 @@ For that you need to send a field `ID` to the backend. Next changes sorted by priority - [x] Fix handler unit tests -- [ ] Switch configuration to TOML +- [x] Switch configuration to Yaml - [ ] Add Authorization (oAuth e.g. Google) - [ ] Add Deletion functionality (depends on the authorization) +- [ ] Performance optimization - [ ] Add ability to track the visitors (Referrer, maybe also live) - [ ] Test docker-compose installation - [ ] Provide image on the docker hub \ No newline at end of file diff --git a/config.yml b/config.yml new file mode 100644 index 0000000..aed84d6 --- /dev/null +++ b/config.yml @@ -0,0 +1,3 @@ +DBPath: main.db +ListenAddr: :8080 +ShortedIDLength: 4 \ No newline at end of file diff --git a/main.go b/main.go index b8b5640..2ff0485 100644 --- a/main.go +++ b/main.go @@ -1,49 +1,63 @@ package main import ( + "io/ioutil" "log" "os" "os/signal" - "strconv" + "path/filepath" "github.com/maxibanki/golang-url-shortener/handlers" "github.com/maxibanki/golang-url-shortener/store" + "github.com/pkg/errors" + yaml "gopkg.in/yaml.v2" ) func main() { - dbPath := "main.db" - listenAddr := ":8080" - idLength := 4 - if os.Getenv("SHORTENER_DB_PATH") != "" { - dbPath = os.Getenv("SHORTENER_DB_PATH") + stop := make(chan os.Signal, 1) + signal.Notify(stop, os.Interrupt) + close, err := initShortener() + if err != nil { + log.Fatalf("could not init shortener: %v", err) } - if os.Getenv("SHORTENER_LISTEN_ADDR") != "" { - listenAddr = os.Getenv("SHORTENER_LISTEN_ADDR") + <-stop + log.Println("Shutting down...") + close() +} + +func initShortener() (func(), error) { + var config struct { + DBPath string `yaml:"DBPath"` + ListenAddr string `yaml:"ListenAddr"` + ShortedIDLength int `yaml:"ShortedIDLength"` } - if os.Getenv("SHORTENER_ID_LENGTH") != "" { - var err error - idLength, err = strconv.Atoi(os.Getenv("SHORTENER_ID_LENGTH")) - if err != nil { - log.Fatalf("could not parse shortener ID length: %v", err) - } + ex, err := os.Executable() + if err != nil { + return nil, errors.Wrap(err, "could not get executable path") } - stop := make(chan os.Signal, 1) - signal.Notify(stop, os.Interrupt) - store, err := store.New(dbPath, idLength) + file, err := ioutil.ReadFile(filepath.Join(filepath.Dir(ex), "config.yml")) + if err != nil { + return nil, errors.Wrap(err, "could not read configuration file: %v") + } + err = yaml.Unmarshal(file, &config) if err != nil { - log.Fatalf("could not create store: %v", err) + return nil, errors.Wrap(err, "could not unmarshal yaml file") } - handler := handlers.New(listenAddr, *store) + store, err := store.New(config.DBPath, config.ShortedIDLength) + if err != nil { + return nil, errors.Wrap(err, "could not create store") + } + handler := handlers.New(config.ListenAddr, *store) go func() { err := handler.Listen() if err != nil { log.Fatalf("could not listen to http handlers: %v", err) } }() - <-stop - log.Println("Shutting down...") - err = handler.CloseStore() - if err != nil { - log.Printf("failed to stop the handlers: %v", err) - } + return func() { + err = handler.CloseStore() + if err != nil { + log.Printf("failed to stop the handlers: %v", err) + } + }, nil } diff --git a/store/store.go b/store/store.go index 6aa2c22..c122ca2 100644 --- a/store/store.go +++ b/store/store.go @@ -3,6 +3,7 @@ package store import ( "encoding/json" + "fmt" "math/rand" "time" @@ -120,6 +121,7 @@ func (s *Store) CreateEntry(URL, remoteAddr string) (string, error) { for i := 1; i <= 10; i++ { id, err := s.createEntry(URL, remoteAddr) if err != nil { + fmt.Println(err) continue } return id, nil