From 315dd5e62f3ed3adba44065e8945e37ab213f86c Mon Sep 17 00:00:00 2001 From: kreativmonkey Date: Sun, 7 May 2017 22:39:37 +0200 Subject: [PATCH] First version with Storage and Counter --- lib/shrt.go | 81 ------------------------------ main.go | 33 ++++--------- short/shrt.go | 112 ++++++++++++++++++++++++++++++++++++++++++ template/index.gohtml | 47 +++++++++++++++++- 4 files changed, 167 insertions(+), 106 deletions(-) delete mode 100644 lib/shrt.go create mode 100644 short/shrt.go diff --git a/lib/shrt.go b/lib/shrt.go deleted file mode 100644 index cd8238d..0000000 --- a/lib/shrt.go +++ /dev/null @@ -1,81 +0,0 @@ -package shrt - -import ( - //"github.com/asaskevich/govalidator" - "fmt" - "crypto/sha256" - "errors" - "io" - "bytes" -) - -type Storage struct { - Token map[string]string `json: tokens` - Url map[string]shrt `json: urls` -} - -type shrt struct { - URL string - Token string - count int -} - -var ( - ErrNotFound = errors.New("Url not Found") - ErrCreateToken = errors.New("There are some problems while creating Token") -) - -func Open() (*Storage, error){ - // Open db ore create if not exist! - s := Storage{Token: make(map[string]string), Url: make(map[string]shrt)} - return &s, nil -} - -func StreamToByte(stream io.Reader) []byte { - buf := new(bytes.Buffer) - buf.ReadFrom(stream) - return buf.Bytes() -} - -func (s *Storage) Add(URL string, value interface{}) (string, error) { - // if the URL a valid URL? - /*if !govalidator.IsURL(URL) { - return "", errors.New("invalid url") - } */ - - // Create a sha256 Hash from the URL - hash := fmt.Sprintf("%x", sha256.Sum256([]byte(URL))) - - // Test if the URL alraedy exist and return the key - if val, ok := s.Url[hash]; ok { - return val.Token, nil - } - // Iterate to the length of hash to get the shortest output - for hashShortestLen := 1; hashShortestLen <= 32; hashShortestLen++ { - // Test if the Token not exist and return the new generated token - if _, ok := s.Token[hash[:hashShortestLen]]; !ok { - token := hash[:hashShortestLen] - s.Token[token] = hash - s.Url[hash] = shrt{URL: URL, Token: token} - value = s.Url[hash] - return token, nil - } - } - - return "", ErrCreateToken -} - -func (s *Storage) Remove(URL string) error { - return nil -} - -// Get returns the URL for the given token -func (s *Storage) Get(token string, value interface{}) bool { - if hash, ok := s.Token[token]; ok { - fmt.Printf("Url gefunden %s mit Hash: %v \n", s.Url[hash].URL, hash) - value = s.Url[hash].URL - fmt.Printf("Value: %V \n", value) - return true - } - return false -} \ No newline at end of file diff --git a/main.go b/main.go index 9ebe90b..085dca5 100644 --- a/main.go +++ b/main.go @@ -3,9 +3,10 @@ package main import ( "net/http" "fmt" + "text/template" + + "github.com/kreativmonkey/shrt/short" "log" - "html/template" - "github.com/kreativmonkey/shrt/lib" ) type Page struct { @@ -30,25 +31,21 @@ func index(w http.ResponseWriter, r *http.Request) { fmt.Println("Path: ", r.URL.Path[1:]) switch r.Method { case "GET": - var redirect string - if ok := short.Get(r.URL.Path[1:], &redirect); ok{ - P := Page{Title: ToString(r.URL.Path[1:]), Body: redirect} - fmt.Printf("Redirect: %s \n", redirect) - t, _ := template.ParseFiles("template/index.gohtml") - t.Execute(w, P) - fmt.Println("Url by Token:", P) + if redirect, ok := short.Get(r.URL.Path[1:]); ok{ + http.Redirect(w, r, string(redirect), 301) + fmt.Printf("Token: %s Redirect to: %s \n", string(r.URL.Path[1:]), redirect) } else { + P := Page{Title: "All: ", Body: short.All ()} t, _ := template.ParseFiles("template/index.gohtml") - t.Execute(w, nil) + t.Execute(w, P) } case "POST": - r.ParseForm() var test string - token, err := short.Add(ToString(r.Form["url"]), &test) + token, err := short.Add(r.FormValue("url"), &test) if err != nil { panic(err) } - P := Page{Title: ToString(r.Form["url"]), Body: token} + P := Page{Title: r.FormValue("url"), Body: token} t, _ := template.ParseFiles("template/index.gohtml") t.Execute(w, P) fmt.Println("Token by Url:", P) @@ -56,20 +53,10 @@ func index(w http.ResponseWriter, r *http.Request) { } -func handelPost(w http.ResponseWriter, r *http.Request){ - -} - func main() { http.HandleFunc("/", index) // setting router rule err := http.ListenAndServe(":9090", nil) // setting listening port if err != nil { log.Fatal("ListenAndServe: ", err) } -} - -// ToString convert the input to a string. -func ToString(obj interface{}) string { - res := fmt.Sprintf("%s", obj) - return string(res) } \ No newline at end of file diff --git a/short/shrt.go b/short/shrt.go new file mode 100644 index 0000000..86663b2 --- /dev/null +++ b/short/shrt.go @@ -0,0 +1,112 @@ +package shrt + +import ( + "fmt" + "crypto/sha256" + "errors" + "encoding/json" + "net/url" + "os" + "io" + "bytes" +) + +type Storage struct { + Token map[string]*shrt + Url map[string]string +} + +type shrt struct { + URL string + Datum string + Count int64 +} + +var ( + ErrNotFound = errors.New("Url not Found") + ErrCreateToken = errors.New("There are some problems while creating Token") + ErrNoUrl = errors.New("String is no Url!") +) + +func Open() (*Storage, error){ + s := Storage{Token: make(map[string]*shrt), Url: make(map[string]string)} + // Open db ore create if not exist! + if db, err := os.OpenFile("./test.db", os.O_RDWR|os.O_CREATE, 0644); err == nil { + json.Unmarshal(StreamToByte(db), &s) + db.Close() + return &s, nil + } else { + return &s, err + } +} + +func (s *Storage) Add(URL string, value interface{}) (string, error) { + // Check if it is a valide Url found on: + // http://stackoverflow.com/questions/31480710/validate-url-with-standard-package-in-go + _, err := url.ParseRequestURI(URL) + if err != nil { + return "", ErrNoUrl + } + + // Create a sha256 Hash from the URL + hash := fmt.Sprintf("%x", sha256.Sum256([]byte(URL))) + + // Test if the URL alraedy exist and return the key + if val, ok := s.Url[hash]; ok { + return val, nil + } + // Iterate to the length of hash to get the shortest output + for hashShortestLen := 1; hashShortestLen <= 32; hashShortestLen++ { + // Test if the Token not exist and return the new generated token + if _, ok := s.Token[hash[:hashShortestLen]]; !ok { + token := hash[:hashShortestLen] + s.Token[token] = &shrt{URL: URL} + s.Url[hash] = token + value = s.Url[hash] + s.Save() + return token, nil + } + } + + return "", ErrCreateToken +} + +func (s *Storage) Remove(URL string) error { + return nil +} + +// Get returns the URL for the given token +func (s *Storage) Get(token string) (string, bool) { + if shrt, ok := s.Token[token]; ok { + fmt.Printf("Url mit dem Token %s gefunden: %s \n", token, shrt.URL) + s.Token[token].Count += 1 + s.Save() + return shrt.URL, true + } + return "", false +} + +func (s *Storage) All() (string) { + b, err := json.Marshal(&s) + if err != nil { + return "" + } + return string(b) +} + +func (s *Storage) Save() error { + if db, err := os.OpenFile("./test.db", os.O_RDWR|os.O_CREATE, 0644); err == nil { + b, err := json.Marshal(&s) + db.Write(b) + db.Close() + return err + } else { + return err + } +} + +func StreamToByte(stream io.Reader) []byte { + buf := new(bytes.Buffer) + buf.ReadFrom(stream) + return buf.Bytes() +} diff --git a/template/index.gohtml b/template/index.gohtml index d75c505..354faba 100644 --- a/template/index.gohtml +++ b/template/index.gohtml @@ -2,14 +2,57 @@ - Title + Shrt + +
+

Shrt

- +
+

Current URL: {{.}}