files impl
parent
c9156f397c
commit
1655a9b83a
|
|
@ -0,0 +1,42 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (rest *REST) entities(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.Method {
|
||||||
|
case http.MethodPut:
|
||||||
|
rest.entitiesReplace(w, r)
|
||||||
|
case http.MethodPatch:
|
||||||
|
rest.entitiesUpdate(w, r)
|
||||||
|
case http.MethodPost:
|
||||||
|
rest.entitiesCreate(w, r)
|
||||||
|
case http.MethodGet:
|
||||||
|
rest.entitiesGet(w, r)
|
||||||
|
case http.MethodDelete:
|
||||||
|
rest.entitiesDelete(w, r)
|
||||||
|
default:
|
||||||
|
http.NotFound(w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rest *REST) entitiesCreate(w http.ResponseWriter, r *http.Request) {
|
||||||
|
http.Error(w, "not impl", http.StatusNotImplemented)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rest *REST) entitiesDelete(w http.ResponseWriter, r *http.Request) {
|
||||||
|
http.Error(w, "not impl", http.StatusNotImplemented)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rest *REST) entitiesGet(w http.ResponseWriter, r *http.Request) {
|
||||||
|
http.Error(w, "not impl", http.StatusNotImplemented)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rest *REST) entitiesReplace(w http.ResponseWriter, r *http.Request) {
|
||||||
|
http.Error(w, "not impl", http.StatusNotImplemented)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rest *REST) entitiesUpdate(w http.ResponseWriter, r *http.Request) {
|
||||||
|
http.Error(w, "not impl", http.StatusNotImplemented)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,108 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"local/dndex/config"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (rest *REST) files(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if len(r.URL.Path) < 2 {
|
||||||
|
http.NotFound(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch r.Method {
|
||||||
|
case http.MethodPut:
|
||||||
|
rest.filesUpdate(w, r)
|
||||||
|
case http.MethodPost:
|
||||||
|
rest.filesCreate(w, r)
|
||||||
|
case http.MethodGet:
|
||||||
|
rest.filesGet(w, r)
|
||||||
|
case http.MethodDelete:
|
||||||
|
rest.filesDelete(w, r)
|
||||||
|
default:
|
||||||
|
http.NotFound(w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rest *REST) filesCreate(w http.ResponseWriter, r *http.Request) {
|
||||||
|
localPath := rest.filesPath(r)
|
||||||
|
if stat, err := os.Stat(localPath); !os.IsNotExist(err) || (stat != nil && stat.IsDir()) {
|
||||||
|
rest.respConflict(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f, err := os.Open(localPath)
|
||||||
|
if err != nil {
|
||||||
|
rest.respError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
if _, err := io.Copy(f, r.Body); err != nil {
|
||||||
|
rest.respError(w, err)
|
||||||
|
}
|
||||||
|
rest.respOK(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rest *REST) filesDelete(w http.ResponseWriter, r *http.Request) {
|
||||||
|
localPath := rest.filesPath(r)
|
||||||
|
if stat, err := os.Stat(localPath); os.IsNotExist(err) {
|
||||||
|
rest.respOK(w)
|
||||||
|
return
|
||||||
|
} else if err != nil || stat.IsDir() {
|
||||||
|
rest.respConflict(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := os.Remove(localPath); err != nil {
|
||||||
|
rest.respError(w, err)
|
||||||
|
}
|
||||||
|
rest.respOK(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rest *REST) filesGet(w http.ResponseWriter, r *http.Request) {
|
||||||
|
localPath := rest.filesPath(r)
|
||||||
|
if stat, err := os.Stat(localPath); os.IsNotExist(err) {
|
||||||
|
http.NotFound(w, r)
|
||||||
|
return
|
||||||
|
} else if err != nil || stat.IsDir() {
|
||||||
|
rest.respConflict(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f, err := os.Open(localPath)
|
||||||
|
if err != nil {
|
||||||
|
rest.respError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
if _, err := io.Copy(w, f); err != nil {
|
||||||
|
rest.respError(w, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rest *REST) filesUpdate(w http.ResponseWriter, r *http.Request) {
|
||||||
|
localPath := rest.filesPath(r)
|
||||||
|
if stat, err := os.Stat(localPath); os.IsNotExist(err) {
|
||||||
|
http.NotFound(w, r)
|
||||||
|
return
|
||||||
|
} else if err != nil || stat.IsDir() {
|
||||||
|
rest.respConflict(w)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f, err := os.Open(localPath)
|
||||||
|
if err != nil {
|
||||||
|
rest.respError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
if _, err := io.Copy(f, r.Body); err != nil {
|
||||||
|
rest.respError(w, err)
|
||||||
|
}
|
||||||
|
rest.respOK(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rest *REST) filesPath(r *http.Request) string {
|
||||||
|
scope := rest.scope(r)
|
||||||
|
localPath := path.Join(config.New().FileRoot, scope.Namespace, r.URL.Path)
|
||||||
|
return localPath
|
||||||
|
}
|
||||||
|
|
@ -2,9 +2,31 @@ package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (rest *REST) respOK(w http.ResponseWriter) {
|
||||||
|
rest.respMap(w, "ok", true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rest *REST) respConflict(w http.ResponseWriter) {
|
||||||
|
rest.respMapStatus(w, "error", "collision found", http.StatusConflict)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rest *REST) respError(w http.ResponseWriter, err error) {
|
||||||
|
rest.respMapStatus(w, "error", fmt.Sprint(err), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rest *REST) respBadRequest(w http.ResponseWriter, msg string) {
|
||||||
|
rest.respMapStatus(w, "error", msg, http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rest *REST) respMapStatus(w http.ResponseWriter, key string, value interface{}, status int) {
|
||||||
|
w.WriteHeader(status)
|
||||||
|
rest.resp(w, map[string]interface{}{key: value})
|
||||||
|
}
|
||||||
|
|
||||||
func (rest *REST) respMap(w http.ResponseWriter, key string, value interface{}) {
|
func (rest *REST) respMap(w http.ResponseWriter, key string, value interface{}) {
|
||||||
rest.resp(w, map[string]interface{}{key: value})
|
rest.resp(w, map[string]interface{}{key: value})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"local/dndex/server/auth"
|
"local/dndex/server/auth"
|
||||||
"local/dndex/storage"
|
"local/dndex/storage"
|
||||||
"local/router"
|
"local/router"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -33,12 +32,11 @@ func NewREST(g storage.RateLimitedGraph) (*REST, error) {
|
||||||
|
|
||||||
param := router.Wildcard
|
param := router.Wildcard
|
||||||
params := router.Wildcard + router.Wildcard
|
params := router.Wildcard + router.Wildcard
|
||||||
_, _ = param, params
|
|
||||||
|
|
||||||
paths := map[string]http.HandlerFunc{
|
paths := map[string]http.HandlerFunc{
|
||||||
fmt.Sprintf("version"): rest.version,
|
fmt.Sprintf("version"): rest.version,
|
||||||
fmt.Sprintf("%s/%s", config.New().FilePrefix, params): rest.files,
|
fmt.Sprintf("%s/%s", config.New().FilePrefix, params): rest.files,
|
||||||
fmt.Sprintf("users"): rest.users,
|
fmt.Sprintf("users/%s", param): rest.users,
|
||||||
fmt.Sprintf("entities/%s", params): rest.entities,
|
fmt.Sprintf("entities/%s", params): rest.entities,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,18 +57,3 @@ func NewREST(g storage.RateLimitedGraph) (*REST, error) {
|
||||||
func (rest *REST) scope(r *http.Request) auth.Scope {
|
func (rest *REST) scope(r *http.Request) auth.Scope {
|
||||||
return auth.GetScope(r)
|
return auth.GetScope(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rest *REST) files(w http.ResponseWriter, r *http.Request) {
|
|
||||||
log.Println("files: SCOPE:", rest.scope(r), r.URL.Path)
|
|
||||||
http.Error(w, "not impl", http.StatusNotImplemented)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rest *REST) users(w http.ResponseWriter, r *http.Request) {
|
|
||||||
log.Println("users: SCOPE:", rest.scope(r), r.URL.Path)
|
|
||||||
http.Error(w, "not impl", http.StatusNotImplemented)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rest *REST) entities(w http.ResponseWriter, r *http.Request) {
|
|
||||||
log.Println("entities: SCOPE:", rest.scope(r), r.URL.Path)
|
|
||||||
http.Error(w, "not impl", http.StatusNotImplemented)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -28,15 +28,12 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRESTRouter(t *testing.T) {
|
func TestRESTRouter(t *testing.T) {
|
||||||
rest, setAuth, clean := testREST(t)
|
_, _, clean := testREST(t)
|
||||||
defer clean()
|
clean()
|
||||||
cases := map[string]struct {
|
cases := map[string]struct {
|
||||||
method string
|
method string
|
||||||
is404 bool
|
is404 bool
|
||||||
}{
|
}{
|
||||||
"/version": {
|
|
||||||
method: http.MethodGet,
|
|
||||||
},
|
|
||||||
fmt.Sprintf(`%s`, config.New().FilePrefix): {
|
fmt.Sprintf(`%s`, config.New().FilePrefix): {
|
||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
is404: true,
|
is404: true,
|
||||||
|
|
@ -45,9 +42,18 @@ func TestRESTRouter(t *testing.T) {
|
||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
is404: true,
|
is404: true,
|
||||||
},
|
},
|
||||||
fmt.Sprintf(`%s/%s`, config.New().FilePrefix, testFilename): {
|
fmt.Sprintf(`%s/%s?g`, config.New().FilePrefix, testFilename): {
|
||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
},
|
},
|
||||||
|
fmt.Sprintf(`%s/%s?pu`, config.New().FilePrefix, testFilename): {
|
||||||
|
method: http.MethodPut,
|
||||||
|
},
|
||||||
|
fmt.Sprintf(`%s/%s?po`, config.New().FilePrefix, testFilename): {
|
||||||
|
method: http.MethodPost,
|
||||||
|
},
|
||||||
|
fmt.Sprintf(`%s/%s?d`, config.New().FilePrefix, testFilename): {
|
||||||
|
method: http.MethodDelete,
|
||||||
|
},
|
||||||
fmt.Sprintf(`%s/fake.fake`, config.New().FilePrefix): {
|
fmt.Sprintf(`%s/fake.fake`, config.New().FilePrefix): {
|
||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
is404: true,
|
is404: true,
|
||||||
|
|
@ -56,19 +62,23 @@ func TestRESTRouter(t *testing.T) {
|
||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
is404: true,
|
is404: true,
|
||||||
},
|
},
|
||||||
fmt.Sprintf("/users/%s", testNamespace): {
|
"/users/register": {
|
||||||
|
method: http.MethodPost,
|
||||||
|
},
|
||||||
|
"/users/login": {
|
||||||
method: http.MethodPost,
|
method: http.MethodPost,
|
||||||
is404: true,
|
|
||||||
},
|
},
|
||||||
"/users/": {
|
"/users/": {
|
||||||
method: http.MethodGet,
|
method: http.MethodPost,
|
||||||
is404: true,
|
is404: true,
|
||||||
},
|
},
|
||||||
"/users": {
|
"/users": {
|
||||||
method: http.MethodPost,
|
method: http.MethodPost,
|
||||||
|
is404: true,
|
||||||
},
|
},
|
||||||
"/users?": {
|
"/users?": {
|
||||||
method: http.MethodGet,
|
method: http.MethodPost,
|
||||||
|
is404: true,
|
||||||
},
|
},
|
||||||
"/entities": {
|
"/entities": {
|
||||||
method: http.MethodGet,
|
method: http.MethodGet,
|
||||||
|
|
@ -124,37 +134,49 @@ func TestRESTRouter(t *testing.T) {
|
||||||
fmt.Sprintf("/entities/%s/connections", testEntityID): {
|
fmt.Sprintf("/entities/%s/connections", testEntityID): {
|
||||||
method: http.MethodPatch,
|
method: http.MethodPatch,
|
||||||
},
|
},
|
||||||
|
"/version": {
|
||||||
|
method: http.MethodGet,
|
||||||
|
},
|
||||||
|
fmt.Sprintf("/entities/%s/connections/uuid/", testEntityID): {
|
||||||
|
method: http.MethodDelete,
|
||||||
|
},
|
||||||
fmt.Sprintf("/entities/%s/connections/uuid", testEntityID): {
|
fmt.Sprintf("/entities/%s/connections/uuid", testEntityID): {
|
||||||
method: http.MethodDelete,
|
method: http.MethodDelete,
|
||||||
},
|
},
|
||||||
fmt.Sprintf("/entities/%s/connections/", testEntityID): {
|
fmt.Sprintf("/entities/%s/connections/?d", testEntityID): {
|
||||||
|
method: http.MethodDelete,
|
||||||
|
},
|
||||||
|
fmt.Sprintf("/entities/%s/connections?d", testEntityID): {
|
||||||
|
method: http.MethodDelete,
|
||||||
|
},
|
||||||
|
fmt.Sprintf("/entities/%s/?d", testEntityID): {
|
||||||
|
method: http.MethodDelete,
|
||||||
|
},
|
||||||
|
fmt.Sprintf("/entities/%s?d", testEntityID): {
|
||||||
|
method: http.MethodDelete,
|
||||||
|
},
|
||||||
|
"/entities/?d": {
|
||||||
method: http.MethodDelete,
|
method: http.MethodDelete,
|
||||||
is404: true,
|
is404: true,
|
||||||
},
|
},
|
||||||
fmt.Sprintf("/entities/%s/connections", testEntityID): {
|
"/entities?d": {
|
||||||
method: http.MethodDelete,
|
|
||||||
},
|
|
||||||
fmt.Sprintf("/entities/%s/", testEntityID): {
|
|
||||||
method: http.MethodDelete,
|
method: http.MethodDelete,
|
||||||
is404: true,
|
is404: true,
|
||||||
},
|
},
|
||||||
fmt.Sprintf("/entities/%s", testEntityID): {
|
|
||||||
method: http.MethodDelete,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, d := range cases {
|
for name, d := range cases {
|
||||||
c := d
|
c := d
|
||||||
path := name
|
path := name
|
||||||
t.Run(name, func(t *testing.T) {
|
rest, setAuth, clean := testREST(t)
|
||||||
|
defer clean()
|
||||||
r := httptest.NewRequest(c.method, path, strings.NewReader(``))
|
r := httptest.NewRequest(c.method, path, strings.NewReader(``))
|
||||||
setAuth(r)
|
setAuth(r)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
rest.router.ServeHTTP(w, r)
|
rest.router.ServeHTTP(w, r)
|
||||||
if (w.Code == http.StatusNotFound) != c.is404 {
|
if (w.Code == http.StatusNotFound) != c.is404 {
|
||||||
t.Fatalf("want 404==%v, got %d: %+v: %s", c.is404, w.Code, c, w.Body.Bytes())
|
t.Errorf("%s: want 404==%v, got %d: %+v: %s", name, c.is404, w.Code, c, w.Body.Bytes())
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -163,14 +185,14 @@ func testREST(t *testing.T) (*REST, func(r *http.Request), func()) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(path.Join(d, testFilename), []byte(testContent), os.ModePerm); err != nil {
|
os.MkdirAll(path.Join(d, testNamespace), os.ModePerm)
|
||||||
|
if err := ioutil.WriteFile(path.Join(d, testNamespace, testFilename), []byte(testContent), os.ModePerm); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
os.Setenv("FILEROOT", d)
|
os.Setenv("FILEROOT", d)
|
||||||
os.Setenv("DRIVER_TYPE", "map")
|
os.Setenv("DRIVER_TYPE", "map")
|
||||||
os.Setenv("AUTH", "true")
|
os.Setenv("AUTH", "true")
|
||||||
os.Args = os.Args[:1]
|
os.Args = os.Args[:1]
|
||||||
os.Args = os.Args[:1]
|
|
||||||
config.New()
|
config.New()
|
||||||
rest, err := NewREST(storage.NewRateLimitedGraph(""))
|
rest, err := NewREST(storage.NewRateLimitedGraph(""))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (rest *REST) users(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.Method {
|
||||||
|
case http.MethodPost:
|
||||||
|
default:
|
||||||
|
http.NotFound(w, r)
|
||||||
|
}
|
||||||
|
switch r.URL.Path {
|
||||||
|
case "/register":
|
||||||
|
rest.usersRegister(w, r)
|
||||||
|
case "/login":
|
||||||
|
rest.usersLogin(w, r)
|
||||||
|
default:
|
||||||
|
http.NotFound(w, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rest *REST) usersRegister(w http.ResponseWriter, r *http.Request) {
|
||||||
|
log.Println(r.URL.Path, rest.scope(r))
|
||||||
|
http.Error(w, "not impl", http.StatusNotImplemented)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rest *REST) usersLogin(w http.ResponseWriter, r *http.Request) {
|
||||||
|
log.Println(r.URL.Path, rest.scope(r))
|
||||||
|
http.Error(w, "not impl", http.StatusNotImplemented)
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue