server strucutre draft

This commit is contained in:
Chapuis Bertil
2015-08-11 14:14:07 +02:00
commit 8eab8b0698
10 changed files with 369 additions and 0 deletions

37
config/config.go Normal file
View File

@@ -0,0 +1,37 @@
package config
import (
"path/filepath"
"github.com/restic/restic/backend"
)
var root string
func Init(path string) {
root = path
}
func ConfigPath(repository string) string {
return filepath.Join(root, repository, string(backend.Config))
}
func DataPath(repository string) string {
return filepath.Join(root, repository, string(backend.Data))
}
func SnapshotPath(repository string) string {
return filepath.Join(root, repository, string(backend.Snapshot))
}
func IndexPath(repository string) string {
return filepath.Join(root, repository, string(backend.Index))
}
func LockPath(repository string) string {
return filepath.Join(root, repository, string(backend.Lock))
}
func KeyPath(repository string) string {
return filepath.Join(root, repository, string(backend.Key))
}

56
handlers/config.go Normal file
View File

@@ -0,0 +1,56 @@
package handlers
import (
"io/ioutil"
"net/http"
"os"
"github.com/bchapuis/restic-server/config"
)
func HeadConfig(w http.ResponseWriter, r *http.Request) {
repo, err := ExtractRepository(r)
if err != nil {
http.Error(w, "403 invalid repository", 403)
return
}
file := config.ConfigPath(repo)
if _, err := os.Stat(file); err != nil {
http.Error(w, "404 repository not found", 404)
return
}
}
func GetConfig(w http.ResponseWriter, r *http.Request) {
repo, err := ExtractRepository(r)
if err != nil {
http.Error(w, "403 invalid repository", 403)
return
}
file := config.ConfigPath(repo)
if _, err := os.Stat(file); err == nil {
bytes, _ := ioutil.ReadFile(file)
w.Write(bytes)
return
} else {
http.Error(w, "404 repository not found", 404)
return
}
}
func PostConfig(w http.ResponseWriter, r *http.Request) {
repo, err := ExtractRepository(r)
if err != nil {
http.Error(w, "403 invalid repository", 403)
return
}
file := config.ConfigPath(repo)
if _, err := os.Stat(file); err == nil {
http.Error(w, "409 repository already initialized", 409)
return
} else {
bytes, _ := ioutil.ReadAll(r.Body)
ioutil.WriteFile(file, bytes, 0600)
return
}
}

53
handlers/data.go Normal file
View File

@@ -0,0 +1,53 @@
package handlers
import (
"fmt"
"net/http"
"path/filepath"
"github.com/bchapuis/restic-server/config"
)
func HeadData(w http.ResponseWriter, r *http.Request) {
repo, err := ExtractRepository(r)
if err != nil {
http.Error(w, "403 invalid repository", 403)
return
}
id, err := ExtractID(r)
if err != nil {
http.Error(w, "403 invalid ID", 403)
return
}
file := filepath.Join(config.DataPath(repo), id)
if _, err := os.Stat(file); err != nil {
http.Error(w, "404 repository not found", 404)
return
}
}
func GetData(w http.ResponseWriter, r *http.Request) {
repo, err := ExtractRepository(r)
if err != nil {
http.Error(w, "403 invalid repository", 403)
return
}
id, err := ExtractID(r)
if err != nil {
http.Error(w, "403 invalid ID", 403)
return
}
file := filepath.Join(config.DataPath(repo), id)
if _, err := os.Stat(file); err != nil {
http.Error(w, "404 repository not found", 404)
return
}
}
func PostData(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "data")
}
func DeleteData(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "data")
}

22
handlers/index.go Normal file
View File

@@ -0,0 +1,22 @@
package handlers
import (
"fmt"
"net/http"
)
func HeadIndex(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "data")
}
func GetIndex(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "index")
}
func PostIndex(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "index")
}
func DeleteIndex(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "index")
}

22
handlers/key.go Normal file
View File

@@ -0,0 +1,22 @@
package handlers
import (
"fmt"
"net/http"
)
func HeadKey(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "data")
}
func GetKey(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "key")
}
func PostKey(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "key")
}
func DeleteKey(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "key")
}

22
handlers/lock.go Normal file
View File

@@ -0,0 +1,22 @@
package handlers
import (
"fmt"
"net/http"
)
func HeadLock(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "data")
}
func GetLock(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "lock")
}
func PostLock(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "lock")
}
func DeleteLock(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "lock")
}

11
handlers/logger.go Normal file
View File

@@ -0,0 +1,11 @@
package handlers
import (
"fmt"
"log"
"net/http"
)
func RequestLogger(w http.ResponseWriter, r *http.Request) {
log.Printf("%v %v", r.Method, r.URL.String())
}

22
handlers/snapshot.go Normal file
View File

@@ -0,0 +1,22 @@
package handlers
import (
"fmt"
"net/http"
)
func HeadSnapshot(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "data")
}
func GetSnapshot(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "snapshot")
}
func PostSnapshot(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "snapshot")
}
func DeleteSnapshot(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "snapshot")
}

25
handlers/variables.go Normal file
View File

@@ -0,0 +1,25 @@
package handlers
import (
"errors"
"net/http"
"strings"
"github.com/restic/restic/backend"
)
func ExtractUser(r *http.Request) (string, string, error) {
return "username", "password", nil
}
func ExtractRepository(r *http.Request) (string, error) {
return "repository", nil
}
func ExtractID(r *http.Request) (backend.ID, error) {
path := strings.Split(r.URL.String(), "/")
if len(path) != 3 {
return backend.ID{}, errors.New("invalid request path")
}
return backend.ParseID(path[2])
}

99
server.go Normal file
View File

@@ -0,0 +1,99 @@
package main
import (
"io/ioutil"
"net/http"
"strings"
"github.com/bchapuis/restic-server/config"
"github.com/bchapuis/restic-server/handlers"
)
type Route struct {
method string
pattern string
handler http.Handler
}
type Router struct {
filters []http.Handler
routes []Route
}
func NewRouter() Router {
filters := []http.Handler{}
routes := []Route{}
return Router{filters, routes}
}
func (router *Router) Filter(handler http.Handler) {
router.filters = append(router.filters, handler)
}
func (router *Router) FilterFunc(handlerFunc http.HandlerFunc) {
router.Filter(handlerFunc)
}
func (router *Router) Handle(method string, pattern string, handler http.Handler) {
router.routes = append(router.routes, Route{method, pattern, handler})
}
func (router *Router) HandleFunc(method string, pattern string, handlerFunc http.HandlerFunc) {
router.Handle(method, pattern, handlerFunc)
}
func (router Router) ServeHTTP(w http.ResponseWriter, r *http.Request) {
for i := 0; i < len(router.filters); i++ {
filter := router.filters[i]
filter.ServeHTTP(w, r)
}
for i := 0; i < len(router.routes); i++ {
route := router.routes[i]
if route.method == r.Method && strings.HasPrefix(r.URL.String(), route.pattern) {
route.handler.ServeHTTP(w, r)
return
}
}
http.NotFound(w, r)
}
func main() {
path, _ := ioutil.TempDir("", "restic-repository-")
config.Init(path)
router := NewRouter()
router.FilterFunc(handlers.RequestLogger)
router.HandleFunc("HEAD", "/config", handlers.HeadConfig)
router.HandleFunc("GET", "/config", handlers.GetConfig)
router.HandleFunc("POST", "/config", handlers.PostConfig)
router.HandleFunc("HEAD", "/data", handlers.HeadData)
router.HandleFunc("GET", "/data", handlers.GetData)
router.HandleFunc("POST", "/data", handlers.PostData)
router.HandleFunc("DELETE", "/data", handlers.DeleteData)
router.HandleFunc("HEAD", "/snapshot", handlers.HeadSnapshot)
router.HandleFunc("GET", "/snapshot", handlers.GetSnapshot)
router.HandleFunc("POST", "/snapshot", handlers.PostSnapshot)
router.HandleFunc("DELETE", "/snapshot", handlers.DeleteSnapshot)
router.HandleFunc("HEAD", "/index", handlers.HeadIndex)
router.HandleFunc("GET", "/index", handlers.GetIndex)
router.HandleFunc("POST", "/index", handlers.PostIndex)
router.HandleFunc("DELETE", "/index", handlers.DeleteIndex)
router.HandleFunc("HEAD", "/lock", handlers.HeadLock)
router.HandleFunc("GET", "/lock", handlers.GetLock)
router.HandleFunc("POST", "/lock", handlers.PostLock)
router.HandleFunc("DELETE", "/lock", handlers.DeleteLock)
router.HandleFunc("HEAD", "/key", handlers.HeadKey)
router.HandleFunc("GET", "/key", handlers.GetKey)
router.HandleFunc("POST", "/key", handlers.PostKey)
router.HandleFunc("DELETE", "/key", handlers.DeleteKey)
http.ListenAndServe(":8000", router)
}