full CRUD resource (put for overriding, delete for ...)

This commit is contained in:
Adrien Marquès 2018-06-16 22:08:14 +02:00
parent 15eb1d5e81
commit 3dfdece7e5
2 changed files with 154 additions and 19 deletions

View File

@ -4,7 +4,7 @@
"info": "redirects to given tiny url", "info": "redirects to given tiny url",
"scope": [[]], "scope": [[]],
"in": { "in": {
"URL#0": { "info": "tiny url to redirect to", "name": "url", "type": "varchar(3,30)" } "URL#0": { "info": "tiny url to redirect to", "name": "url", "type": "varchar(1,30)" }
}, },
"out": {} "out": {}
}, },
@ -13,10 +13,29 @@
"info": "creates a new tiny url", "info": "creates a new tiny url",
"scope": [[]], "scope": [[]],
"in": { "in": {
"url": { "info": "preferred tiny url", "type": "varchar(3,30)" }, "URL#0": { "info": "preferred tiny url", "type": "varchar(1,30)", "name": "url" },
"target": { "info": "url to shorten", "type": "varchar(5,300)" } "target": { "info": "url to shorten", "type": "varchar(5,300)" }
}, },
"out": {} "out": {}
},
"PUT": {
"info": "overrides an existing tiny url",
"scope": [[]],
"in": {
"URL#0": { "info": "preferred tiny url", "type": "varchar(1,30)", "name": "url" },
"target": { "info": "url to shorten", "type": "varchar(5,300)" }
},
"out": {}
},
"DELETE": {
"info": "removes an existing tiny url",
"scope": [[]],
"in": {
"URL#0": { "info": "preferred tiny url", "type": "varchar(1,30)", "name": "url" }
},
"out": {}
} }
} }

150
root/i.go
View File

@ -1,30 +1,79 @@
package main package main
import ( import (
"fmt"
e "git.xdrm.io/go/xb-api/err" e "git.xdrm.io/go/xb-api/err"
i "git.xdrm.io/go/xb-api/implement" i "git.xdrm.io/go/xb-api/implement"
r "github.com/go-redis/redis" "github.com/go-redis/redis"
) )
// Initiates connection to redis dataset const NONCE = "go-tiny-url"
func redisConnect() (*r.Client, error) {
cli := r.NewClient(&r.Options{ type db redis.Client
// Returns a connected client to dataset
func connect() *db {
cli := redis.NewClient(&redis.Options{
Addr: "127.0.0.1:6379", Addr: "127.0.0.1:6379",
Password: "", Password: "",
DB: 0, DB: 0,
}) })
_, err := cli.Ping().Result() 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
return cli, err
} }
// Redirects to an url from a key // Redirects to an url from a key
func Get(d i.Arguments, r *i.Response) i.Response { func Get(d i.Arguments, r *i.Response) i.Response {
/* (1) Init redis connection */ /* (1) Init redis connection */
cli, err := redisConnect() cli := connect()
if err != nil { if cli == nil {
r.Err = e.Failure r.Err = e.Failure
return *r return *r
} }
@ -39,14 +88,14 @@ func Get(d i.Arguments, r *i.Response) i.Response {
} }
/* (3) Check if match for this key */ /* (3) Check if match for this key */
val, err := cli.Get(key).Result() val := cli.get(key)
if err != nil { if val == nil {
r.Err = e.NoMatchFound r.Err = e.NoMatchFound
return *r return *r
} }
/* (4) Redirect to value */ /* (4) Redirect to value */
r.Set("_REDIRECT_", val) r.Set("_REDIRECT_", string(val))
r.Err = e.Success r.Err = e.Success
return *r return *r
} }
@ -54,8 +103,8 @@ func Get(d i.Arguments, r *i.Response) i.Response {
// Stores a new tinyurl/fullurl combination // Stores a new tinyurl/fullurl combination
func Post(d i.Arguments, r *i.Response) i.Response { func Post(d i.Arguments, r *i.Response) i.Response {
/* (1) Init redis connection */ /* (1) Init redis connection */
cli, err := redisConnect() cli := connect()
if err != nil { if cli == nil {
r.Err = e.Failure r.Err = e.Failure
return *r return *r
} }
@ -70,15 +119,82 @@ func Post(d i.Arguments, r *i.Response) i.Response {
} }
/* (3) Check if key already used */ /* (3) Check if key already used */
_, err = cli.Get(url).Result() if cli.get(url) != nil {
if err == nil {
r.Err = e.AlreadyExists r.Err = e.AlreadyExists
return *r return *r
} }
/* (4) Store */ /* (4) Store */
err = cli.Set(url, target, 0).Err() if !cli.set(url, target) {
if err != nil { 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 r.Err = e.Failure
return *r return *r
} }