2010-06-12 21:45:58 +00:00
|
|
|
// Copyright 2010 Brad Fitzpatrick <brad@danga.com>
|
|
|
|
//
|
|
|
|
// See LICENSE.
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
2010-07-11 04:18:16 +00:00
|
|
|
import (
|
2010-11-29 04:06:22 +00:00
|
|
|
"camli/auth"
|
2010-12-06 06:34:46 +00:00
|
|
|
"camli/httputil"
|
2010-12-06 06:29:11 +00:00
|
|
|
"camli/webserver"
|
2011-02-03 23:45:35 +00:00
|
|
|
"camli/blobserver"
|
2011-02-03 23:56:02 +00:00
|
|
|
"camli/blobserver/handlers"
|
2010-07-11 04:18:16 +00:00
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"http"
|
2011-01-26 05:33:19 +00:00
|
|
|
"log"
|
2011-02-03 06:42:31 +00:00
|
|
|
"strings"
|
2010-07-11 04:18:16 +00:00
|
|
|
"os"
|
|
|
|
)
|
2010-07-07 04:57:53 +00:00
|
|
|
|
2010-07-26 05:18:21 +00:00
|
|
|
var flagStorageRoot *string = flag.String("root", "/tmp/camliroot", "Root directory to store files")
|
2011-01-26 05:33:19 +00:00
|
|
|
var flagRequestLog *bool = flag.Bool("reqlog", false, "Log incoming requests")
|
2010-06-12 21:45:58 +00:00
|
|
|
|
2011-02-03 23:45:35 +00:00
|
|
|
var storage blobserver.Storage
|
2011-02-03 06:42:31 +00:00
|
|
|
|
|
|
|
const camliPrefix = "/camli/"
|
|
|
|
const partitionPrefix = "/partition-"
|
|
|
|
|
|
|
|
var InvalidCamliPath = os.NewError("Invalid Camlistore request path")
|
|
|
|
|
2011-02-04 01:08:04 +00:00
|
|
|
func parseCamliPath(path string) (partition blobserver.Partition, action string, err os.Error) {
|
2011-02-03 06:42:31 +00:00
|
|
|
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
|
|
|
|
}
|
2011-02-04 01:08:04 +00:00
|
|
|
name := path[len(partitionPrefix):camIdx]
|
|
|
|
if !isValidPartitionName(name) {
|
2011-02-03 06:42:31 +00:00
|
|
|
err = InvalidCamliPath
|
|
|
|
return
|
|
|
|
}
|
2011-02-04 01:08:04 +00:00
|
|
|
partition = blobserver.Partition(name)
|
2011-02-03 06:42:31 +00:00
|
|
|
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-12-14 02:20:31 +00:00
|
|
|
|
2010-10-04 15:28:14 +00:00
|
|
|
func handleCamli(conn http.ResponseWriter, req *http.Request) {
|
2011-02-03 06:42:31 +00:00
|
|
|
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
|
|
|
}
|
2011-02-03 06:42:31 +00:00
|
|
|
|
|
|
|
handler := unsupportedHandler
|
2011-01-26 05:33:19 +00:00
|
|
|
if *flagRequestLog {
|
2011-02-03 06:42:31 +00:00
|
|
|
log.Printf("method %q; partition %q; action %q", req.Method, partition, action)
|
2011-01-26 05:33:19 +00:00
|
|
|
}
|
2010-07-11 04:18:16 +00:00
|
|
|
switch req.Method {
|
|
|
|
case "GET":
|
2011-02-03 06:42:31 +00:00
|
|
|
switch action {
|
|
|
|
case "enumerate-blobs":
|
2011-02-04 01:08:04 +00:00
|
|
|
handler = auth.RequireAuth(handlers.CreateEnumerateHandler(storage, partition))
|
2010-07-26 05:18:21 +00:00
|
|
|
default:
|
2011-02-04 01:28:05 +00:00
|
|
|
handler = handlers.CreateGetHandler(storage)
|
2010-07-26 05:18:21 +00:00
|
|
|
}
|
2010-07-11 04:18:16 +00:00
|
|
|
case "POST":
|
2011-02-03 06:42:31 +00:00
|
|
|
switch action {
|
|
|
|
case "preupload":
|
2010-11-15 03:52:52 +00:00
|
|
|
handler = auth.RequireAuth(handlePreUpload)
|
2011-02-03 06:42:31 +00:00
|
|
|
case "upload":
|
2010-11-15 03:52:52 +00:00
|
|
|
handler = auth.RequireAuth(handleMultiPartUpload)
|
2011-02-03 06:42:31 +00:00
|
|
|
case "remove":
|
|
|
|
// Currently only allows removing from a non-main partition.
|
2011-02-03 23:56:02 +00:00
|
|
|
handler = auth.RequireAuth(handlers.CreateRemoveHandler(storage, partition))
|
2011-02-03 06:42:31 +00:00
|
|
|
|
|
|
|
// Not part of the spec:
|
|
|
|
case "testform": // debug only
|
2010-07-18 18:08:45 +00:00
|
|
|
handler = handleTestForm
|
2011-02-03 06:42:31 +00:00
|
|
|
case "form": // debug only
|
2010-07-18 18:08:45 +00:00
|
|
|
handler = handleCamliForm
|
2010-07-11 04:18:16 +00:00
|
|
|
}
|
|
|
|
case "PUT": // no longer part of spec
|
2010-11-15 03:52:52 +00:00
|
|
|
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()
|
|
|
|
|
2010-11-15 03:52:52 +00:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-03 23:45:35 +00:00
|
|
|
storage = newDiskStorage(*flagStorageRoot)
|
2010-12-14 02:20:31 +00:00
|
|
|
|
2010-12-06 06:29:11 +00:00
|
|
|
ws := webserver.New()
|
2011-02-03 06:42:31 +00:00
|
|
|
ws.RegisterPreMux(webserver.HandlerPicker(pickPartitionHandlerMaybe))
|
2010-12-06 06:29:11 +00:00
|
|
|
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
|
|
|
}
|