perkeep/server/go/blobserver/camlistored.go

142 lines
3.5 KiB
Go
Raw Normal View History

2010-06-12 21:45:58 +00:00
// Copyright 2010 Brad Fitzpatrick <brad@danga.com>
//
// See LICENSE.
package main
import (
2010-11-29 04:06:22 +00:00
"camli/auth"
2010-12-06 06:34:46 +00:00
"camli/httputil"
"camli/webserver"
"camli/blobserver"
"camli/blobserver/handlers"
"flag"
"fmt"
"http"
"log"
"strings"
"os"
)
2010-07-26 05:18:21 +00:00
var flagStorageRoot *string = flag.String("root", "/tmp/camliroot", "Root directory to store files")
var flagRequestLog *bool = flag.Bool("reqlog", false, "Log incoming requests")
2010-06-12 21:45:58 +00:00
var storage blobserver.Storage
const camliPrefix = "/camli/"
const partitionPrefix = "/partition-"
var InvalidCamliPath = os.NewError("Invalid Camlistore request path")
func parseCamliPath(path string) (partition blobserver.Partition, action string, err os.Error) {
camIdx := strings.Index(path, camliPrefix)
if camIdx == -1 {
err = InvalidCamliPath
return
}
action = path[camIdx+len(camliPrefix):]
if camIdx == 0 {
return
}
if !strings.HasPrefix(path, partitionPrefix) {
err = InvalidCamliPath
return
}
name := path[len(partitionPrefix):camIdx]
if !isValidPartitionName(name) {
err = InvalidCamliPath
return
}
partition = blobserver.Partition(name)
return
}
func pickPartitionHandlerMaybe(req *http.Request) (handler http.HandlerFunc, intercept bool) {
if !strings.HasPrefix(req.URL.Path, partitionPrefix) {
intercept = false
return
}
return http.HandlerFunc(handleCamli), true
}
func unsupportedHandler(conn http.ResponseWriter, req *http.Request) {
httputil.BadRequestError(conn, "Unsupported camlistore path or method.")
}
2010-10-04 15:28:14 +00:00
func handleCamli(conn http.ResponseWriter, req *http.Request) {
partition, action, err := parseCamliPath(req.URL.Path)
if err != nil {
log.Printf("Invalid request for method %q, path %q",
req.Method, req.URL.Path)
unsupportedHandler(conn, req)
return
2010-07-18 18:08:45 +00:00
}
handler := unsupportedHandler
if *flagRequestLog {
log.Printf("method %q; partition %q; action %q", req.Method, partition, action)
}
switch req.Method {
case "GET":
switch action {
case "enumerate-blobs":
handler = auth.RequireAuth(handlers.CreateEnumerateHandler(storage, partition))
2010-07-26 05:18:21 +00:00
default:
handler = handlers.CreateGetHandler(storage)
2010-07-26 05:18:21 +00:00
}
case "POST":
switch action {
case "preupload":
handler = auth.RequireAuth(handlePreUpload)
case "upload":
handler = auth.RequireAuth(handleMultiPartUpload)
case "remove":
// Currently only allows removing from a non-main partition.
handler = auth.RequireAuth(handlers.CreateRemoveHandler(storage, partition))
// Not part of the spec:
case "testform": // debug only
2010-07-18 18:08:45 +00:00
handler = handleTestForm
case "form": // debug only
2010-07-18 18:08:45 +00:00
handler = handleCamliForm
}
case "PUT": // no longer part of spec
handler = auth.RequireAuth(handlePut)
2010-06-13 00:15:49 +00:00
}
2010-07-18 18:08:45 +00:00
handler(conn, req)
2010-06-12 21:45:58 +00:00
}
2010-10-04 15:28:14 +00:00
func handleRoot(conn http.ResponseWriter, req *http.Request) {
2011-01-29 08:05:07 +00:00
fmt.Fprintf(conn, "This is camlistored, a Camlistore storage daemon.\n")
2010-06-12 21:45:58 +00:00
}
func main() {
flag.Parse()
auth.AccessPassword = os.Getenv("CAMLI_PASSWORD")
if len(auth.AccessPassword) == 0 {
2010-06-12 21:45:58 +00:00
fmt.Fprintf(os.Stderr,
"No CAMLI_PASSWORD environment variable set.\n")
os.Exit(1)
}
{
2010-07-26 05:18:21 +00:00
fi, err := os.Stat(*flagStorageRoot)
2010-06-12 21:45:58 +00:00
if err != nil || !fi.IsDirectory() {
fmt.Fprintf(os.Stderr,
"Storage root '%s' doesn't exist or is not a directory.\n",
2010-07-26 05:18:21 +00:00
*flagStorageRoot)
2010-06-12 21:45:58 +00:00
os.Exit(1)
}
}
storage = newDiskStorage(*flagStorageRoot)
ws := webserver.New()
ws.RegisterPreMux(webserver.HandlerPicker(pickPartitionHandlerMaybe))
ws.HandleFunc("/", handleRoot)
ws.HandleFunc("/camli/", handleCamli)
ws.Handle("/js/", http.FileServer("../../clients/js", "/js/"))
ws.Serve()
2010-06-12 21:45:58 +00:00
}