files impl

master
breel 2020-08-08 10:57:46 -06:00
parent c9156f397c
commit 1655a9b83a
6 changed files with 256 additions and 47 deletions

42
server/entities.go Normal file
View File

@ -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)
}

108
server/files.go Normal file
View File

@ -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
}

View File

@ -2,9 +2,31 @@ package server
import (
"encoding/json"
"fmt"
"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{}) {
rest.resp(w, map[string]interface{}{key: value})
}

View File

@ -6,7 +6,6 @@ import (
"local/dndex/server/auth"
"local/dndex/storage"
"local/router"
"log"
"net/http"
)
@ -33,12 +32,11 @@ func NewREST(g storage.RateLimitedGraph) (*REST, error) {
param := router.Wildcard
params := router.Wildcard + router.Wildcard
_, _ = param, params
paths := map[string]http.HandlerFunc{
fmt.Sprintf("version"): rest.version,
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,
}
@ -59,18 +57,3 @@ func NewREST(g storage.RateLimitedGraph) (*REST, error) {
func (rest *REST) scope(r *http.Request) auth.Scope {
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)
}

View File

@ -28,15 +28,12 @@ var (
)
func TestRESTRouter(t *testing.T) {
rest, setAuth, clean := testREST(t)
defer clean()
_, _, clean := testREST(t)
clean()
cases := map[string]struct {
method string
is404 bool
}{
"/version": {
method: http.MethodGet,
},
fmt.Sprintf(`%s`, config.New().FilePrefix): {
method: http.MethodGet,
is404: true,
@ -45,9 +42,18 @@ func TestRESTRouter(t *testing.T) {
method: http.MethodGet,
is404: true,
},
fmt.Sprintf(`%s/%s`, config.New().FilePrefix, testFilename): {
fmt.Sprintf(`%s/%s?g`, config.New().FilePrefix, testFilename): {
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): {
method: http.MethodGet,
is404: true,
@ -56,19 +62,23 @@ func TestRESTRouter(t *testing.T) {
method: http.MethodGet,
is404: true,
},
fmt.Sprintf("/users/%s", testNamespace): {
"/users/register": {
method: http.MethodPost,
},
"/users/login": {
method: http.MethodPost,
is404: true,
},
"/users/": {
method: http.MethodGet,
method: http.MethodPost,
is404: true,
},
"/users": {
method: http.MethodPost,
is404: true,
},
"/users?": {
method: http.MethodGet,
method: http.MethodPost,
is404: true,
},
"/entities": {
method: http.MethodGet,
@ -124,37 +134,49 @@ func TestRESTRouter(t *testing.T) {
fmt.Sprintf("/entities/%s/connections", testEntityID): {
method: http.MethodPatch,
},
"/version": {
method: http.MethodGet,
},
fmt.Sprintf("/entities/%s/connections/uuid/", testEntityID): {
method: http.MethodDelete,
},
fmt.Sprintf("/entities/%s/connections/uuid", testEntityID): {
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,
is404: true,
},
fmt.Sprintf("/entities/%s/connections", testEntityID): {
method: http.MethodDelete,
},
fmt.Sprintf("/entities/%s/", testEntityID): {
"/entities?d": {
method: http.MethodDelete,
is404: true,
},
fmt.Sprintf("/entities/%s", testEntityID): {
method: http.MethodDelete,
},
}
for name, d := range cases {
c := d
path := name
t.Run(name, func(t *testing.T) {
rest, setAuth, clean := testREST(t)
defer clean()
r := httptest.NewRequest(c.method, path, strings.NewReader(``))
setAuth(r)
w := httptest.NewRecorder()
rest.router.ServeHTTP(w, r)
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 {
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)
}
os.Setenv("FILEROOT", d)
os.Setenv("DRIVER_TYPE", "map")
os.Setenv("AUTH", "true")
os.Args = os.Args[:1]
os.Args = os.Args[:1]
config.New()
rest, err := NewREST(storage.NewRateLimitedGraph(""))
if err != nil {

32
server/users.go Normal file
View File

@ -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)
}