mirror of
https://github.com/restic/rest-server.git
synced 2025-10-19 15:43:21 +00:00
new router implementation
This commit is contained in:
parent
c19c63325c
commit
d4717695cb
2 changed files with 191 additions and 80 deletions
83
router.go
Normal file
83
router.go
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Route struct {
|
||||||
|
path []string
|
||||||
|
handler http.Handler
|
||||||
|
}
|
||||||
|
|
||||||
|
type Router struct {
|
||||||
|
routes map[string][]Route
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRouter() *Router {
|
||||||
|
return &Router{make(map[string][]Route)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router *Router) Options(path string, handler http.HandlerFunc) {
|
||||||
|
router.Handle("OPTIONS", path, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router *Router) Get(path string, handler http.HandlerFunc) {
|
||||||
|
router.Handle("GET", path, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router *Router) Head(path string, handler http.HandlerFunc) {
|
||||||
|
router.Handle("HEAD", path, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router *Router) Post(path string, handler http.HandlerFunc) {
|
||||||
|
router.Handle("POST", path, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router *Router) Put(path string, handler http.HandlerFunc) {
|
||||||
|
router.Handle("PUT", path, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router *Router) Delete(path string, handler http.HandlerFunc) {
|
||||||
|
router.Handle("DELETE", path, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router *Router) Trace(path string, handler http.HandlerFunc) {
|
||||||
|
router.Handle("TRACE", path, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router *Router) Connect(path string, handler http.HandlerFunc) {
|
||||||
|
router.Handle("Connect", path, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router *Router) Handle(method string, uri string, handler http.HandlerFunc) {
|
||||||
|
routes := router.routes[method]
|
||||||
|
path := strings.Split(uri, "/")
|
||||||
|
routes = append(routes, Route{path, handler})
|
||||||
|
router.routes[method] = routes
|
||||||
|
}
|
||||||
|
|
||||||
|
func (router *Router) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
|
method := r.Method
|
||||||
|
uri := r.RequestURI
|
||||||
|
path := strings.Split(uri, "/")
|
||||||
|
|
||||||
|
log.Printf("%s %s", method, uri)
|
||||||
|
|
||||||
|
ROUTE:
|
||||||
|
for _, route := range router.routes[method] {
|
||||||
|
if len(route.path) != len(path) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for i := 0; i < len(route.path); i++ {
|
||||||
|
if !strings.HasPrefix(route.path[i], ":") && route.path[i] != path[i] {
|
||||||
|
continue ROUTE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
route.handler.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
http.Error(w, "404 not found", 404)
|
||||||
|
}
|
188
server.go
188
server.go
|
@ -37,92 +37,120 @@ func main() {
|
||||||
os.MkdirAll(filepath.Join(*path, d), backend.Modes.Dir)
|
os.MkdirAll(filepath.Join(*path, d), backend.Modes.Dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
router := http.NewServeMux()
|
router := NewRouter()
|
||||||
|
|
||||||
// Check if a configuration exists.
|
router.Head("/config", func(w http.ResponseWriter, r *http.Request) {
|
||||||
router.HandleFunc("/config", func(w http.ResponseWriter, r *http.Request) {
|
config := filepath.Join(*path, "config")
|
||||||
uri := r.RequestURI
|
if _, err := os.Stat(config); err != nil {
|
||||||
method := r.Method
|
http.Error(w, "404 not found", 404)
|
||||||
log.Printf("%s %s", method, uri)
|
|
||||||
|
|
||||||
file := filepath.Join(*path, "config")
|
|
||||||
_, err := os.Stat(file)
|
|
||||||
|
|
||||||
// Check if the config exists
|
|
||||||
if method == "HEAD" && err == nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
w.Write([]byte("200 ok"))
|
||||||
// Get the config
|
|
||||||
if method == "GET" && err == nil {
|
|
||||||
bytes, _ := ioutil.ReadFile(file)
|
|
||||||
w.Write(bytes)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the config
|
|
||||||
if method == "POST" && err != nil {
|
|
||||||
bytes, _ := ioutil.ReadAll(r.Body)
|
|
||||||
ioutil.WriteFile(file, bytes, 0600)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
http.Error(w, "404 not found", 404)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
for _, dir := range dirs {
|
router.Get("/config", func(w http.ResponseWriter, r *http.Request) {
|
||||||
router.HandleFunc("/"+dir+"/", func(w http.ResponseWriter, r *http.Request) {
|
config := filepath.Join(*path, "config")
|
||||||
uri := r.RequestURI
|
bytes, err := ioutil.ReadFile(config)
|
||||||
method := r.Method
|
if err != nil {
|
||||||
log.Printf("%s %s", method, uri)
|
|
||||||
|
|
||||||
vars := strings.Split(r.RequestURI, "/")
|
|
||||||
dir := vars[1]
|
|
||||||
name := vars[2]
|
|
||||||
path := filepath.Join(*path, dir, name)
|
|
||||||
_, err := os.Stat(path)
|
|
||||||
|
|
||||||
// List the blobs of a given dir.
|
|
||||||
if method == "GET" && name == "" && err == nil {
|
|
||||||
files, _ := ioutil.ReadDir(path)
|
|
||||||
names := make([]string, len(files))
|
|
||||||
for i, f := range files {
|
|
||||||
names[i] = f.Name()
|
|
||||||
}
|
|
||||||
data, _ := json.Marshal(names)
|
|
||||||
w.Write(data)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the blob esists
|
|
||||||
if method == "HEAD" && name != "" && err == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get a blob of a given dir.
|
|
||||||
if method == "GET" && name != "" && err == nil {
|
|
||||||
file, _ := os.Open(path)
|
|
||||||
defer file.Close()
|
|
||||||
http.ServeContent(w, r, "", time.Unix(0, 0), file)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save a blob
|
|
||||||
if method == "POST" && name != "" && err != nil {
|
|
||||||
bytes, _ := ioutil.ReadAll(r.Body)
|
|
||||||
ioutil.WriteFile(path, bytes, 0600)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete a blob
|
|
||||||
if method == "DELETE" && name != "" && err == nil {
|
|
||||||
os.Remove(path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
http.Error(w, "404 not found", 404)
|
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"))
|
||||||
|
})
|
||||||
|
|
||||||
// start the server
|
// start the server
|
||||||
if !*tls {
|
if !*tls {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue