package main import ( "fmt" e "git.xdrm.io/go/xb-api/err" i "git.xdrm.io/go/xb-api/implement" "github.com/go-redis/redis" ) const NONCE = "go-tiny-url" type db redis.Client // Returns a connected client to dataset func connect() *db { cli := redis.NewClient(&redis.Options{ Addr: "127.0.0.1:6379", Password: "", DB: 0, }) if _, err := cli.Ping().Result(); err != nil { return nil } return (*db)(cli) } // returns value from key (nil if nothing) func (c *db) get(key string) []byte { // 1. Try to get if val, err := c.Get(fmt.Sprintf("%s:%s", NONCE, key)).Result(); err != nil { // 2. nil if nothing found return nil } else { // 3. return if found return []byte(val) } } // stores a value for a key (success state in return) func (c *db) set(key string, value string) bool { // 1. Try to set if c.Set(fmt.Sprintf("%s:%s", NONCE, key), value, 0).Err() != nil { // 2. failure return false } // 3. success return true } // deletes the value for a key (success state in return) func (c *db) del(key string) bool { // 1. Try to set if c.Del(fmt.Sprintf("%s:%s", NONCE, key)).Err() != nil { // 2. failure return false } // 3. success return true } // Redirects to an url from a key func Get(d i.Arguments, r *i.Response) i.Response { /* (1) Init redis connection */ cli := connect() if cli == nil { r.Err = e.Failure return *r } /* (2) Extract api input */ key, ok := d["url"].(string) if !ok { r.Err = e.InvalidParam r.Err.BindArgument("url") return *r } /* (3) Check if match for this key */ val := cli.get(key) if val == nil { r.Err = e.NoMatchFound return *r } /* (4) Redirect to value */ r.Set("_REDIRECT_", string(val)) r.Err = e.Success return *r } // Stores a new tinyurl/fullurl combination func Post(d i.Arguments, r *i.Response) i.Response { /* (1) Init redis connection */ cli := connect() if cli == nil { r.Err = e.Failure return *r } /* (2) Extract api input */ target, ok1 := d["target"].(string) url, ok2 := d["url"].(string) if !ok1 || !ok2 { r.Err = e.InvalidParam return *r } /* (3) Check if key already used */ if cli.get(url) != nil { r.Err = e.AlreadyExists return *r } /* (4) Store */ if !cli.set(url, target) { r.Err = e.Failure return *r } r.Err = e.Success return *r } // Overrides a existing tinyurl with new target func Put(d i.Arguments, r *i.Response) i.Response { /* (1) Init redis connection */ cli := connect() if cli == nil { r.Err = e.Failure return *r } /* (2) Extract api input */ target, ok1 := d["target"].(string) url, ok2 := d["url"].(string) if !ok1 || !ok2 { r.Err = e.InvalidParam return *r } /* (3) Check if key already used */ if cli.get(url) == nil { r.Err = e.NoMatchFound return *r } /* (4) Update */ if !cli.set(url, target) { r.Err = e.Failure return *r } r.Err = e.Success return *r } // Deletes an existing tinyurl func Delete(d i.Arguments, r *i.Response) i.Response { /* (1) Init redis connection */ cli := connect() if cli == nil { r.Err = e.Failure return *r } /* (2) Extract api input */ url, ok := d["url"].(string) if !ok { r.Err = e.InvalidParam return *r } /* (3) Check if key already used */ if cli.get(url) == nil { r.Err = e.NoMatchFound return *r } /* (4) Delete */ if !cli.del(url) { r.Err = e.Failure return *r } r.Err = e.Success return *r }