rest-server/main.go

155 lines
4.1 KiB
Go
Raw Normal View History

2015-08-11 14:14:07 +02:00
package main
2015-08-15 10:06:10 +02:00
import (
"log"
"net/http"
2015-09-16 23:34:11 +02:00
"os"
2015-09-07 15:29:24 +02:00
"path/filepath"
2016-12-30 21:56:07 +01:00
"runtime"
2016-11-06 19:38:41 +01:00
"runtime/pprof"
2015-08-11 14:14:07 +02:00
"github.com/gorilla/handlers"
2016-12-30 20:57:48 +01:00
"github.com/spf13/cobra"
"goji.io"
"goji.io/pat"
)
2016-12-27 12:26:41 +01:00
2016-12-30 20:57:48 +01:00
// cmdRoot is the base command when no other command has been specified.
var cmdRoot = &cobra.Command{
Use: "rest-server",
Short: "Run a REST server for use with restic",
SilenceErrors: true,
SilenceUsage: true,
RunE: runRoot,
}
var config = struct {
path string
listen string
tls bool
log string
2016-12-30 20:57:48 +01:00
cpuprofile string
debug bool
}{}
func init() {
flags := cmdRoot.Flags()
flags.StringVar(&config.cpuprofile, "cpuprofile", "", "write CPU profile to file")
flags.BoolVar(&config.debug, "debug", false, "output debug messages")
flags.StringVar(&config.listen, "listen", ":8000", "listen address")
flags.StringVar(&config.log, "log", "", "log HTTP requests in the combined log format")
flags.StringVar(&config.path, "path", "/tmp/restic", "data directory")
flags.BoolVar(&config.tls, "tls", false, "turn on TLS support")
2016-12-30 20:57:48 +01:00
}
2015-09-16 23:34:11 +02:00
2016-12-28 00:57:25 +01:00
func debugHandler(next http.Handler) http.Handler {
return http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
log.Printf("%s %s", r.Method, r.URL)
next.ServeHTTP(w, r)
})
}
func logHandler(next http.Handler) http.Handler {
accessLog, err := os.OpenFile(config.log, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
log.Fatal(err)
}
return handlers.CombinedLoggingHandler(accessLog, next)
}
func setupMux() *goji.Mux {
mux := goji.NewMux()
2016-12-28 00:57:25 +01:00
2016-12-30 20:57:48 +01:00
if config.debug {
2016-12-28 00:57:25 +01:00
mux.Use(debugHandler)
}
if config.log != "" {
mux.Use(logHandler)
}
mux.HandleFunc(pat.Head("/config"), CheckConfig)
2016-12-28 00:57:25 +01:00
mux.HandleFunc(pat.Head("/:repo/config"), CheckConfig)
mux.HandleFunc(pat.Get("/config"), GetConfig)
2016-12-28 00:57:25 +01:00
mux.HandleFunc(pat.Get("/:repo/config"), GetConfig)
mux.HandleFunc(pat.Post("/config"), SaveConfig)
2016-12-28 00:57:25 +01:00
mux.HandleFunc(pat.Post("/:repo/config"), SaveConfig)
mux.HandleFunc(pat.Delete("/config"), DeleteConfig)
mux.HandleFunc(pat.Delete("/:repo/config"), DeleteConfig)
mux.HandleFunc(pat.Get("/:type/"), ListBlobs)
2016-12-28 00:57:25 +01:00
mux.HandleFunc(pat.Get("/:repo/:type/"), ListBlobs)
mux.HandleFunc(pat.Head("/:type/:name"), CheckBlob)
2016-12-28 00:57:25 +01:00
mux.HandleFunc(pat.Head("/:repo/:type/:name"), CheckBlob)
mux.HandleFunc(pat.Get("/:type/:name"), GetBlob)
2016-12-28 00:57:25 +01:00
mux.HandleFunc(pat.Get("/:repo/:type/:name"), GetBlob)
mux.HandleFunc(pat.Post("/:type/:name"), SaveBlob)
2016-12-28 00:57:25 +01:00
mux.HandleFunc(pat.Post("/:repo/:type/:name"), SaveBlob)
mux.HandleFunc(pat.Delete("/:type/:name"), DeleteBlob)
2016-12-28 00:57:25 +01:00
mux.HandleFunc(pat.Delete("/:repo/:type/:name"), DeleteBlob)
mux.HandleFunc(pat.Post("/"), CreateRepo)
mux.HandleFunc(pat.Post("/:repo"), CreateRepo)
2017-04-01 10:20:06 +02:00
mux.HandleFunc(pat.Post("/:repo/"), CreateRepo)
2015-09-16 23:34:11 +02:00
return mux
2016-11-11 01:24:06 +01:00
}
2016-12-30 21:56:07 +01:00
var version = "manually"
2016-12-30 20:57:48 +01:00
func runRoot(cmd *cobra.Command, args []string) error {
2016-11-11 01:24:06 +01:00
log.SetFlags(0)
2016-12-30 21:56:07 +01:00
log.Printf("rest-server %s compiled with %v on %v/%v\n", version, runtime.Version(), runtime.GOOS, runtime.GOARCH)
2017-01-16 23:19:51 +01:00
log.Printf("Data directory: %s", config.path)
2016-12-30 21:56:07 +01:00
2016-12-30 20:57:48 +01:00
if config.cpuprofile != "" {
f, err := os.Create(config.cpuprofile)
2016-11-11 01:24:06 +01:00
if err != nil {
log.Fatal(err)
}
if err := pprof.StartCPUProfile(f); err != nil {
log.Fatal(err)
}
log.Println("CPU profiling enabled")
defer pprof.StopCPUProfile()
}
mux := setupMux()
2016-11-11 01:24:06 +01:00
2015-09-19 14:52:50 +02:00
var handler http.Handler
2016-12-30 20:57:48 +01:00
htpasswdFile, err := NewHtpasswdFromFile(filepath.Join(config.path, ".htpasswd"))
2015-09-19 14:52:50 +02:00
if err != nil {
handler = mux
2016-11-11 01:24:06 +01:00
log.Println("Authentication disabled")
2015-09-19 14:52:50 +02:00
} else {
handler = AuthHandler(htpasswdFile, mux)
2016-11-11 01:24:06 +01:00
log.Println("Authentication enabled")
2015-09-19 14:52:50 +02:00
}
2016-12-30 20:57:48 +01:00
if !config.tls {
log.Printf("Starting server on %s\n", config.listen)
err = http.ListenAndServe(config.listen, handler)
2015-09-07 15:29:24 +02:00
} else {
2016-12-30 20:57:48 +01:00
privateKey := filepath.Join(config.path, "private_key")
publicKey := filepath.Join(config.path, "public_key")
2015-09-19 14:52:50 +02:00
log.Println("TLS enabled")
2016-11-06 12:11:32 +01:00
log.Printf("Private key: %s", privateKey)
log.Printf("Public key: %s", publicKey)
2016-12-30 20:57:48 +01:00
log.Printf("Starting server on %s\n", config.listen)
err = http.ListenAndServeTLS(config.listen, publicKey, privateKey, handler)
2016-11-06 12:11:32 +01:00
}
if err != nil {
log.Fatal(err)
2015-09-07 15:29:24 +02:00
}
2016-12-30 20:57:48 +01:00
return nil
}
func main() {
2017-01-16 23:15:16 +01:00
if err := cmdRoot.Execute(); err != nil {
log.Fatalf("error: %v", err)
2016-12-30 20:57:48 +01:00
}
2015-08-11 14:14:07 +02:00
}