Skip to content

Commit

Permalink
[#2]: Force data marshaling into JSON object
Browse files Browse the repository at this point in the history
New path: */v1/get/path/to/the/node+json*
Method: *GET*

Fixes #2
  • Loading branch information
Difrex committed Aug 1, 2019
1 parent b1818dc commit 2b5273c
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 62 deletions.
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
language: go
go:
- 1.6
- 1.7
- 1.8
- 1.9
- 1.11
- 1.12

# tests script
script:
Expand Down
14 changes: 12 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
FROM alpine
FROM golang:1.12 AS builder

COPY . /go/src/github.com/Difrex/zoorest
WORKDIR /go/src/github.com/Difrex/zoorest

ENV CGO_ENABLED=0

RUN go get -t -v ./...
RUN go build -o /zoorest .

FROM alpine AS final

MAINTAINER Denis Zheleztsov <[email protected]>

ADD out/zoorest /bin/
COPY --from=builder /zoorest /bin/zoorest

RUN echo -ne "zoorest\nzoorest\n" | adduser zoorest

Expand Down
83 changes: 72 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Zoorest
# Zoorest
[![Build Status](https://travis-ci.org/Difrex/zoorest.svg?branch=master)](https://travis-ci.org/Difrex/zoorest)

Zookeeper HTTP rest API
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-generate-toc again -->
Zookeeper REST API
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
**Table of Contents**

- [Zoorest](#zoorest)
Expand All @@ -11,14 +11,16 @@ Zookeeper HTTP rest API
- [List node childrens](#list-node-childrens)
- [Errors](#errors)
- [Get node data](#get-node-data)
- [Errors](#errors)
- [Errors](#errors-1)
- [Get node data as JSON](#get-node-data-as-json)
- [Errors](#errors-2)
- [Create node recursive](#create-node-recursive)
- [Create node children](#create-node-children)
- [Errors](#errors)
- [Errors](#errors-3)
- [Update node](#update-node)
- [Errors](#errors)
- [Errors](#errors-4)
- [Delete node recursive](#delete-node-recursive)
- [Errors](#errors)
- [Errors](#errors-5)
- [Build](#build)
- [Binary](#binary)
- [Docker build](#docker-build)
Expand Down Expand Up @@ -124,6 +126,65 @@ echo eyJzb21lIjogImpzb24ifQ== | base64 -d
}
```

### Get node data as JSON

Method: **GET**

Location: **/v1/get/path/to/node+json**

Simple add to the end of the path `+json`
Return JSON
```
curl -s -XGET http://127.0.0.1:8889/v1/json/one/data+json | jq
{
"path": "/json/one/data",
"state": "OK",
"error": "",
"zkstat": {
"Czxid": 45,
"Mzxid": 55,
"Ctime": 1564645641612,
"Mtime": 1564646317882,
"Version": 6,
"Cversion": 0,
"Aversion": 0,
"EphemeralOwner": 0,
"DataLength": 28,
"NumChildren": 0,
"Pzxid": 45
},
"data": {
"ok": true,
"some": "data"
}
}
```

#### Errors

```json
curl -s -XGET http://127.0.0.1:8889/v1/get/invalid/json+json | jq
{
"path": "/invalid/json",
"state": "OK",
"error": "JSON parsing failure: invalid character 'i' looking for beginning of value",
"zkstat": {
"Czxid": 45,
"Mzxid": 56,
"Ctime": 1564645641612,
"Mtime": 1564646350753,
"Version": 7,
"Cversion": 0,
"Aversion": 0,
"EphemeralOwner": 0,
"DataLength": 17,
"NumChildren": 0,
"Pzxid": 45
},
"data": null
}
```

### Create node recursive

Method: **PUT**
Expand Down Expand Up @@ -230,11 +291,11 @@ go build -compile gccgo

#### Binary file

Build binary file
Build binary with the Docker
```
git clone https://github.com/Difrex/zoorest.git
cd zoorest
./build.sh
./build.sh docker-binary
```
Result binary file will be placed in out/ dir

Expand All @@ -244,7 +305,7 @@ Build Alpine based docker image
```
git clone https://github.com/Difrex/zoorest.git
cd zoorest
./build.sh alpine
./build.sh docker
```

Image will be tagged as zoorest:latest
Expand All @@ -265,7 +326,7 @@ And run it

Denis Zheleztsov <[email protected]>

# LICENSE
# LICENSE

GPLv3 see [LICENSE](LICENSE)

Expand Down
32 changes: 9 additions & 23 deletions build.sh
Original file line number Diff line number Diff line change
@@ -1,29 +1,15 @@
#!/bin/bash

cat > Dockerfile.builder <<EOF
FROM golang
MAINTAINER Denis Zheleztsov <[email protected]>
ENV GOPATH /usr
RUN go get github.com/Difrex/zoorest/rest
RUN cd /usr/src/github.com/Difrex/zoorest && go get -t -v ./...
WORKDIR /usr/src/github.com/Difrex/zoorest
ENTRYPOINT go build -ldflags "-linkmode external -extldflags -static" && mv zoorest /out
EOF

# Build builder
docker build --no-cache -t zoorest_builder -f Dockerfile.builder .
# Build bin
docker run -v $(pwd)/out:/out zoorest_builder

case $1 in alpine)
case $1 in docker)
docker build -t zoorest -f Dockerfile .
;;
binary)
go build -o zoorest .
;;
docker-binary)
docker build --rm -t zoorest -f Dockerfile .
docker run --rm -u root -v $(pwd)/out:/tmp/out --entrypoint '/bin/cp' zoorest /bin/zoorest /tmp/out
;;
*)
;;
;;
esac

104 changes: 81 additions & 23 deletions rest/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ package rest

import (
"encoding/json"
"github.com/gorilla/mux"
"github.com/samuel/go-zookeeper/zk"
"io/ioutil"
"log"
"net/http"
"strings"
"time"

"github.com/gorilla/mux"
"github.com/samuel/go-zookeeper/zk"
)

// Ls ...
Expand All @@ -29,14 +30,16 @@ type Get struct {
Data []byte `json:"data"`
}

type GetJSON struct {
Path string `json:"path"`
State string `json:"state"`
Error string `json:"error"`
ZkStat *zk.Stat `json:"zkstat"`
Data interface{} `json:"data"`
}

// LS ...
func (zk ZooNode) LS(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
e := strings.Join([]string{"Method", r.Method, "not alowed"}, " ")
w.WriteHeader(500)
w.Write([]byte(e))
return
}
vars := mux.Vars(r)
path := vars["path"]

Expand Down Expand Up @@ -108,12 +111,6 @@ func (zk ZooNode) UP(w http.ResponseWriter, r *http.Request) {

// RM ...
func (zk ZooNode) RM(w http.ResponseWriter, r *http.Request) {
if r.Method != "DELETE" {
e := strings.Join([]string{"Method", r.Method, "not alowed"}, " ")
w.WriteHeader(500)
w.Write([]byte(e))
return
}
vars := mux.Vars(r)
path := vars["path"]

Expand All @@ -139,12 +136,33 @@ func (zk ZooNode) RM(w http.ResponseWriter, r *http.Request) {

// GET ...
func (zk ZooNode) GET(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
e := strings.Join([]string{"Method", r.Method, "not alowed"}, " ")
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)
w.Write([]byte(e))
w.Write([]byte("JSON parsing failure"))
return
}

if childrens.Error != "" {
w.WriteHeader(500)
w.Write(data)
return
}

w.WriteHeader(200)
w.Write(data)
}

// GetJSON marshals the node data to the JSON
func (zk ZooNode) GetJSON(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
path := vars["path"]

Expand All @@ -166,18 +184,39 @@ func (zk ZooNode) GET(w http.ResponseWriter, r *http.Request) {
return
}

w.WriteHeader(200)
w.Write(data)
dataJson, err := unmarhalNodeData(childrens.Data)
if err != nil {
w.WriteHeader(500)
childrens.Error = "JSON parsing failure: " + err.Error()
w.Write(errorUnmarshal(childrens))
return
}

getJson := GetJSON{
Path: childrens.Path,
Error: childrens.Error,
State: childrens.State,
ZkStat: childrens.ZkStat,
Data: dataJson,
}
if data, err := json.Marshal(getJson); err != nil {
w.WriteHeader(500)
w.Write([]byte(err.Error()))
} else {
w.WriteHeader(200)
w.Write(data)
}
}

// Serve ...
func Serve(listen string, zk ZooNode) {
r := mux.NewRouter()

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)
r.HandleFunc("/v1/ls{path:[A-Za-z0-9-_/.:]+}", zk.LS).Methods("GET")
r.HandleFunc("/v1/get{path:[A-Za-z0-9-_/.:]+}", zk.GET).Methods("GET")
r.HandleFunc("/v1/get{path:[A-Za-z0-9-_/.:]+}+json", zk.GetJSON).Methods("GET")
r.HandleFunc("/v1/rmr{path:[A-Za-z0-9-_/.:]+}", zk.RM).Methods("DELETE")
r.HandleFunc("/v1/up{path:[A-Za-z0-9-_/.:]+}", zk.UP).Methods("PUT", "POST", "PATCH")

http.Handle("/", r)

Expand All @@ -191,3 +230,22 @@ func Serve(listen string, zk ZooNode) {
log.Print("Listening API on ", listen)
log.Fatal(srv.ListenAndServe())
}

func unmarhalNodeData(data []byte) (interface{}, error) {
var content interface{}
err := json.Unmarshal(data, &content)
if err != nil {
return nil, err
}

return content, nil
}

func errorUnmarshal(get Get) []byte {
get.Data = nil
data, err := json.Marshal(get)
if err != nil {
return nil
}
return data
}

0 comments on commit 2b5273c

Please sign in to comment.