diff --git a/handler.go b/handler.go new file mode 100644 index 0000000..3e5a8eb --- /dev/null +++ b/handler.go @@ -0,0 +1,142 @@ +package main + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "os" + "path/filepath" + "strings" + "time" +) + +type Context struct { + path string +} + +func CheckConfig(c *Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + config := filepath.Join(c.path, "config") + if _, err := os.Stat(config); err != nil { + http.Error(w, "404 not found", 404) + return + } + } +} + +func GetConfig(c *Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + config := filepath.Join(c.path, "config") + bytes, err := ioutil.ReadFile(config) + if err != nil { + http.Error(w, "404 not found", 404) + return + } + w.Write(bytes) + } +} + +func SaveConfig(c *Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + config := filepath.Join(c.path, "config") + bytes, err := ioutil.ReadAll(r.Body) + if err != nil { + http.Error(w, "400 bad request", 400) + return + } + errw := ioutil.WriteFile(config, bytes, 0600) + if errw != nil { + http.Error(w, "500 internal server error", 500) + return + } + w.Write([]byte("200 ok")) + } +} + +func ListBlobs(c *Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + vars := strings.Split(r.RequestURI, "/") + dir := vars[1] + path := filepath.Join(c.path, dir) + files, err := ioutil.ReadDir(path) + if err != nil { + http.Error(w, "404 not found", 404) + return + } + names := make([]string, len(files)) + for i, f := range files { + names[i] = f.Name() + } + data, err := json.Marshal(names) + if err != nil { + http.Error(w, "500 internal server error", 500) + return + } + w.Write(data) + } +} + +func CheckBlob(c *Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + vars := strings.Split(r.RequestURI, "/") + dir := vars[1] + name := vars[2] + path := filepath.Join(c.path, dir, name) + _, err := os.Stat(path) + if err != nil { + http.Error(w, "404 not found", 404) + return + } + } +} + +func GetBlob(c *Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + vars := strings.Split(r.RequestURI, "/") + dir := vars[1] + name := vars[2] + path := filepath.Join(c.path, dir, name) + file, err := os.Open(path) + if err != nil { + http.Error(w, "404 not found", 404) + return + } + defer file.Close() + http.ServeContent(w, r, "", time.Unix(0, 0), file) + } +} + +func SaveBlob(c *Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + vars := strings.Split(r.RequestURI, "/") + dir := vars[1] + name := vars[2] + path := filepath.Join(c.path, dir, name) + bytes, err := ioutil.ReadAll(r.Body) + if err != nil { + http.Error(w, "400 bad request", 400) + return + } + errw := ioutil.WriteFile(path, bytes, 0600) + if errw != nil { + http.Error(w, "500 internal server error", 500) + return + } + w.Write([]byte("200 ok")) + } +} + +func DeleteBlob(c *Context) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + vars := strings.Split(r.RequestURI, "/") + dir := vars[1] + name := vars[2] + path := filepath.Join(c.path, dir, name) + err := os.Remove(path) + if err != nil { + http.Error(w, "500 internal server error", 500) + return + } + w.Write([]byte("200 ok")) + } +} diff --git a/router.go b/router.go index cd430c9..c0a3028 100644 --- a/router.go +++ b/router.go @@ -19,39 +19,71 @@ func NewRouter() *Router { return &Router{make(map[string][]Route)} } -func (router *Router) Options(path string, handler http.HandlerFunc) { +func (router *Router) Options(path string, handler http.Handler) { router.Handle("OPTIONS", path, handler) } -func (router *Router) Get(path string, handler http.HandlerFunc) { +func (router *Router) OptionsFunc(path string, handler http.HandlerFunc) { + router.Handle("OPTIONS", path, handler) +} + +func (router *Router) Get(path string, handler http.Handler) { router.Handle("GET", path, handler) } -func (router *Router) Head(path string, handler http.HandlerFunc) { +func (router *Router) GetFunc(path string, handler http.HandlerFunc) { + router.Handle("GET", path, handler) +} + +func (router *Router) Head(path string, handler http.Handler) { router.Handle("HEAD", path, handler) } -func (router *Router) Post(path string, handler http.HandlerFunc) { +func (router *Router) HeadFunc(path string, handler http.HandlerFunc) { + router.Handle("HEAD", path, handler) +} + +func (router *Router) Post(path string, handler http.Handler) { router.Handle("POST", path, handler) } -func (router *Router) Put(path string, handler http.HandlerFunc) { +func (router *Router) PostFunc(path string, handler http.HandlerFunc) { + router.Handle("POST", path, handler) +} + +func (router *Router) Put(path string, handler http.Handler) { router.Handle("PUT", path, handler) } -func (router *Router) Delete(path string, handler http.HandlerFunc) { +func (router *Router) PutFunc(path string, handler http.HandlerFunc) { + router.Handle("PUT", path, handler) +} + +func (router *Router) Delete(path string, handler http.Handler) { router.Handle("DELETE", path, handler) } -func (router *Router) Trace(path string, handler http.HandlerFunc) { +func (router *Router) DeleteFunc(path string, handler http.HandlerFunc) { + router.Handle("DELETE", path, handler) +} + +func (router *Router) Trace(path string, handler http.Handler) { router.Handle("TRACE", path, handler) } -func (router *Router) Connect(path string, handler http.HandlerFunc) { +func (router *Router) TraceFunc(path string, handler http.HandlerFunc) { + router.Handle("TRACE", path, handler) +} + +func (router *Router) Connect(path string, handler http.Handler) { router.Handle("Connect", path, handler) } -func (router *Router) Handle(method string, uri string, handler http.HandlerFunc) { +func (router *Router) ConnectFunc(path string, handler http.HandlerFunc) { + router.Handle("Connect", path, handler) +} + +func (router *Router) Handle(method string, uri string, handler http.Handler) { routes := router.routes[method] path := strings.Split(uri, "/") routes = append(routes, Route{path, handler}) diff --git a/router_test.go b/router_test.go index f5127d6..f7b1f43 100644 --- a/router_test.go +++ b/router_test.go @@ -14,22 +14,22 @@ func TestRouter(t *testing.T) { router := NewRouter() getConfig := []byte("GET /config") - router.Get("/config", func(w http.ResponseWriter, r *http.Request) { + router.GetFunc("/config", func(w http.ResponseWriter, r *http.Request) { w.Write(getConfig) }) postConfig := []byte("POST /config") - router.Post("/config", func(w http.ResponseWriter, r *http.Request) { + router.PostFunc("/config", func(w http.ResponseWriter, r *http.Request) { w.Write(postConfig) }) getBlobs := []byte("GET /blobs/") - router.Get("/blobs/", func(w http.ResponseWriter, r *http.Request) { + router.GetFunc("/blobs/", func(w http.ResponseWriter, r *http.Request) { w.Write(getBlobs) }) getBlob := []byte("GET /blobs/:sha") - router.Get("/blobs/:sha", func(w http.ResponseWriter, r *http.Request) { + router.GetFunc("/blobs/:sha", func(w http.ResponseWriter, r *http.Request) { w.Write(getBlob) }) diff --git a/server.go b/server.go index 2382954..989d9c5 100644 --- a/server.go +++ b/server.go @@ -1,15 +1,11 @@ package main import ( - "encoding/json" "flag" - "io/ioutil" "log" "net/http" "os" "path/filepath" - "strings" - "time" "github.com/restic/restic/backend" ) @@ -37,120 +33,17 @@ func main() { os.MkdirAll(filepath.Join(*path, d), backend.Modes.Dir) } + context := &Context{*path} + router := NewRouter() - - router.Head("/config", func(w http.ResponseWriter, r *http.Request) { - config := filepath.Join(*path, "config") - if _, err := os.Stat(config); err != nil { - http.Error(w, "404 not found", 404) - return - } - w.Write([]byte("200 ok")) - }) - - router.Get("/config", func(w http.ResponseWriter, r *http.Request) { - config := filepath.Join(*path, "config") - bytes, err := ioutil.ReadFile(config) - if err != nil { - http.Error(w, "404 not found", 404) - return - } - w.Write(bytes) - }) - - router.Post("/config", func(w http.ResponseWriter, r *http.Request) { - config := filepath.Join(*path, "config") - bytes, err := ioutil.ReadAll(r.Body) - if err != nil { - http.Error(w, "400 bad request", 400) - return - } - errw := ioutil.WriteFile(config, bytes, 0600) - if errw != nil { - http.Error(w, "500 internal server error", 500) - return - } - w.Write([]byte("200 ok")) - }) - - router.Get("/:dir/", func(w http.ResponseWriter, r *http.Request) { - vars := strings.Split(r.RequestURI, "/") - dir := vars[1] - path := filepath.Join(*path, dir) - files, err := ioutil.ReadDir(path) - if err != nil { - http.Error(w, "404 not found", 404) - return - } - names := make([]string, len(files)) - for i, f := range files { - names[i] = f.Name() - } - data, err := json.Marshal(names) - if err != nil { - http.Error(w, "500 internal server error", 500) - return - } - w.Write(data) - }) - - router.Head("/:dir/:name", func(w http.ResponseWriter, r *http.Request) { - vars := strings.Split(r.RequestURI, "/") - dir := vars[1] - name := vars[2] - path := filepath.Join(*path, dir, name) - _, err := os.Stat(path) - if err != nil { - http.Error(w, "404 not found", 404) - return - } - w.Write([]byte("200 ok")) - }) - - router.Get("/:type/:name", func(w http.ResponseWriter, r *http.Request) { - vars := strings.Split(r.RequestURI, "/") - dir := vars[1] - name := vars[2] - path := filepath.Join(*path, dir, name) - file, err := os.Open(path) - if err != nil { - http.Error(w, "404 not found", 404) - return - } - defer file.Close() - http.ServeContent(w, r, "", time.Unix(0, 0), file) - }) - - router.Post("/:type/:name", func(w http.ResponseWriter, r *http.Request) { - vars := strings.Split(r.RequestURI, "/") - dir := vars[1] - name := vars[2] - path := filepath.Join(*path, dir, name) - bytes, err := ioutil.ReadAll(r.Body) - if err != nil { - http.Error(w, "400 bad request", 400) - return - } - errw := ioutil.WriteFile(path, bytes, 0600) - if errw != nil { - http.Error(w, "500 internal server error", 500) - return - } - w.Write([]byte("200 ok")) - }) - - router.Delete("/:type/:name", func(w http.ResponseWriter, r *http.Request) { - vars := strings.Split(r.RequestURI, "/") - dir := vars[1] - name := vars[2] - path := filepath.Join(*path, dir, name) - err := os.Remove(path) - if err != nil { - http.Error(w, "500 internal server error", 500) - return - } - w.Write([]byte("200 ok")) - }) + router.HeadFunc("/config", CheckConfig(context)) + router.GetFunc("/config", GetConfig(context)) + router.PostFunc("/config", SaveConfig(context)) + router.GetFunc("/:dir/", ListBlobs(context)) + router.HeadFunc("/:dir/:name", CheckBlob(context)) + router.GetFunc("/:type/:name", GetBlob(context)) + router.PostFunc("/:type/:name", SaveBlob(context)) + router.DeleteFunc("/:type/:name", DeleteBlob(context)) // start the server if !*tls {