2017-02-15 17:09:28 +03:00
|
|
|
package rest
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"github.com/gorilla/mux"
|
2017-02-18 20:12:50 +03:00
|
|
|
"github.com/samuel/go-zookeeper/zk"
|
2017-02-17 11:05:54 +03:00
|
|
|
"io/ioutil"
|
2017-02-15 17:09:28 +03:00
|
|
|
"log"
|
|
|
|
"net/http"
|
2017-02-17 11:05:54 +03:00
|
|
|
"strings"
|
2017-02-15 17:09:28 +03:00
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Ls ...
|
|
|
|
type Ls struct {
|
|
|
|
Childrens []string `json:"childrens"`
|
|
|
|
Path string `json:"path"`
|
|
|
|
State string `json:"state"`
|
2017-02-15 17:24:58 +03:00
|
|
|
Error string `json:"error"`
|
2017-02-18 20:12:50 +03:00
|
|
|
ZkStat *zk.Stat `json:"zkstat"`
|
2017-02-15 17:09:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get ...
|
|
|
|
type Get struct {
|
2017-02-18 20:12:50 +03:00
|
|
|
Path string `json:"path"`
|
|
|
|
State string `json:"state"`
|
|
|
|
Error string `json:"error"`
|
|
|
|
ZkStat *zk.Stat `json:"zkstat"`
|
|
|
|
Data []byte `json:"data"`
|
2017-02-15 17:09:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// LS ...
|
|
|
|
func (zk ZooNode) LS(w http.ResponseWriter, r *http.Request) {
|
2017-02-17 12:34:43 +03:00
|
|
|
if r.Method != "GET" {
|
|
|
|
e := strings.Join([]string{"Method", r.Method, "not alowed"}, " ")
|
|
|
|
w.WriteHeader(500)
|
|
|
|
w.Write([]byte(e))
|
|
|
|
return
|
|
|
|
}
|
2017-02-15 17:09:28 +03:00
|
|
|
vars := mux.Vars(r)
|
|
|
|
path := vars["path"]
|
|
|
|
|
|
|
|
ch := make(chan Ls)
|
|
|
|
|
|
|
|
go func() { ch <- zk.GetChildrens(path) }()
|
|
|
|
|
|
|
|
childrens := <-ch
|
|
|
|
data, err := json.Marshal(childrens)
|
|
|
|
if err != nil {
|
|
|
|
w.WriteHeader(500)
|
2017-02-15 17:24:58 +03:00
|
|
|
w.Write([]byte("JSON parsing failure"))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if childrens.Error != "" {
|
|
|
|
w.WriteHeader(500)
|
|
|
|
w.Write(data)
|
|
|
|
return
|
2017-02-15 17:09:28 +03:00
|
|
|
}
|
2017-02-15 17:24:58 +03:00
|
|
|
|
2017-02-15 17:09:28 +03:00
|
|
|
w.WriteHeader(200)
|
|
|
|
w.Write(data)
|
|
|
|
}
|
|
|
|
|
2017-02-17 11:05:54 +03:00
|
|
|
// ReadRequestBody ...
|
|
|
|
func ReadRequestBody(req *http.Request) ([]byte, error) {
|
|
|
|
body, err := ioutil.ReadAll(req.Body)
|
|
|
|
if err != nil {
|
|
|
|
return []byte(""), err
|
|
|
|
}
|
|
|
|
|
|
|
|
return body, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// UP ...
|
|
|
|
func (zk ZooNode) UP(w http.ResponseWriter, r *http.Request) {
|
|
|
|
vars := mux.Vars(r)
|
|
|
|
path := vars["path"]
|
|
|
|
|
|
|
|
ch := make(chan string)
|
|
|
|
// Read request body as []byte
|
|
|
|
content, err := ReadRequestBody(r)
|
|
|
|
if err != nil {
|
|
|
|
w.WriteHeader(500)
|
|
|
|
w.Write([]byte(err.Error()))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create node
|
|
|
|
if r.Method == "PUT" {
|
|
|
|
go func() { ch <- zk.CreateNode(path, content) }()
|
|
|
|
} else if r.Method == "POST" {
|
|
|
|
go func() { ch <- zk.UpdateNode(path, content) }()
|
2017-05-04 18:45:29 +03:00
|
|
|
} else if r.Method == "PATCH" {
|
|
|
|
go func() { ch <- zk.CreateChild(path, content) }()
|
2017-02-17 11:05:54 +03:00
|
|
|
} else {
|
2017-02-17 12:34:43 +03:00
|
|
|
e := strings.Join([]string{"Method", r.Method, "not alowed"}, " ")
|
2017-02-17 11:05:54 +03:00
|
|
|
w.WriteHeader(500)
|
|
|
|
w.Write([]byte(e))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
defer r.Body.Close()
|
|
|
|
|
|
|
|
state := <-ch
|
|
|
|
|
|
|
|
w.WriteHeader(200)
|
|
|
|
w.Write([]byte(state))
|
|
|
|
}
|
|
|
|
|
2017-02-15 19:13:12 +03:00
|
|
|
// RM ...
|
|
|
|
func (zk ZooNode) RM(w http.ResponseWriter, r *http.Request) {
|
2017-02-17 12:34:43 +03:00
|
|
|
if r.Method != "DELETE" {
|
|
|
|
e := strings.Join([]string{"Method", r.Method, "not alowed"}, " ")
|
2017-02-17 11:05:54 +03:00
|
|
|
w.WriteHeader(500)
|
|
|
|
w.Write([]byte(e))
|
|
|
|
return
|
|
|
|
}
|
2017-02-15 19:13:12 +03:00
|
|
|
vars := mux.Vars(r)
|
|
|
|
path := vars["path"]
|
|
|
|
|
2017-02-17 12:34:43 +03:00
|
|
|
if path == "/" {
|
|
|
|
e := "Skiping root path"
|
|
|
|
w.WriteHeader(500)
|
|
|
|
w.Write([]byte(e))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-05-04 18:45:29 +03:00
|
|
|
var rmPath string
|
|
|
|
rmPath = strings.Join([]string{zk.Path, path}, "")
|
|
|
|
|
2017-02-17 12:34:43 +03:00
|
|
|
if strings.Contains(rmPath, "//") {
|
|
|
|
rmPath = strings.Replace(rmPath, "//", "/", 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
go func() { zk.RMR(rmPath) }()
|
2017-02-15 19:13:12 +03:00
|
|
|
|
|
|
|
w.WriteHeader(200)
|
2017-05-04 16:44:22 +03:00
|
|
|
w.Write([]byte(path))
|
2017-02-15 19:13:12 +03:00
|
|
|
}
|
|
|
|
|
2017-02-15 17:09:28 +03:00
|
|
|
// GET ...
|
|
|
|
func (zk ZooNode) GET(w http.ResponseWriter, r *http.Request) {
|
2017-02-17 12:34:43 +03:00
|
|
|
if r.Method != "GET" {
|
|
|
|
e := strings.Join([]string{"Method", r.Method, "not alowed"}, " ")
|
|
|
|
w.WriteHeader(500)
|
|
|
|
w.Write([]byte(e))
|
|
|
|
return
|
|
|
|
}
|
2017-02-15 17:09:28 +03:00
|
|
|
vars := mux.Vars(r)
|
|
|
|
path := vars["path"]
|
|
|
|
|
|
|
|
ch := make(chan Get)
|
|
|
|
|
|
|
|
go func() { ch <- zk.GetNode(path) }()
|
|
|
|
|
|
|
|
childrens := <-ch
|
|
|
|
data, err := json.Marshal(childrens)
|
|
|
|
if err != nil {
|
|
|
|
w.WriteHeader(500)
|
2017-02-15 17:24:58 +03:00
|
|
|
w.Write([]byte("JSON parsing failure"))
|
|
|
|
return
|
2017-02-15 17:09:28 +03:00
|
|
|
}
|
2017-02-15 17:24:58 +03:00
|
|
|
|
|
|
|
if childrens.Error != "" {
|
|
|
|
w.WriteHeader(500)
|
|
|
|
w.Write(data)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-02-15 17:09:28 +03:00
|
|
|
w.WriteHeader(200)
|
|
|
|
w.Write(data)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Serve ...
|
|
|
|
func Serve(listen string, zk ZooNode) {
|
|
|
|
r := mux.NewRouter()
|
|
|
|
|
2017-05-04 18:45:29 +03:00
|
|
|
r.HandleFunc("/v1/ls{path:[A-Za-z0-9-_/.:]+}", zk.LS)
|
|
|
|
r.HandleFunc("/v1/get{path:[A-Za-z0-9-_/.:]+}", zk.GET)
|
|
|
|
r.HandleFunc("/v1/rmr{path:[A-Za-z0-9-_/.:]+}", zk.RM)
|
|
|
|
r.HandleFunc("/v1/up{path:[A-Za-z0-9-_/.:]+}", zk.UP)
|
2017-02-15 17:09:28 +03:00
|
|
|
|
|
|
|
http.Handle("/", r)
|
|
|
|
|
|
|
|
srv := http.Server{
|
|
|
|
Handler: r,
|
|
|
|
Addr: listen,
|
|
|
|
WriteTimeout: 15 * time.Second,
|
|
|
|
ReadTimeout: 15 * time.Second,
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Print("Listening API on ", listen)
|
|
|
|
log.Fatal(srv.ListenAndServe())
|
|
|
|
}
|