diff --git a/server/go/Makefile b/server/go/Makefile new file mode 100644 index 000000000..d52cb1eaf --- /dev/null +++ b/server/go/Makefile @@ -0,0 +1,9 @@ +all: + make -C auth install + make -C http_util install + make -C blobserver + +clean: + make -C auth clean + make -C http_util clean + make -C blobserver clean diff --git a/server/go/auth/Makefile b/server/go/auth/Makefile new file mode 100644 index 000000000..a69e53cba --- /dev/null +++ b/server/go/auth/Makefile @@ -0,0 +1,7 @@ +include $(GOROOT)/src/Make.inc + +TARG=auth +GOFILES=\ + auth.go + +include $(GOROOT)/src/Make.pkg diff --git a/server/go/blobserver/auth.go b/server/go/auth/auth.go similarity index 83% rename from server/go/blobserver/auth.go rename to server/go/auth/auth.go index 77f39f390..472164394 100644 --- a/server/go/blobserver/auth.go +++ b/server/go/auth/auth.go @@ -1,4 +1,4 @@ -package main +package auth import ( "encoding/base64" @@ -10,9 +10,9 @@ import ( var kBasicAuthPattern *regexp.Regexp = regexp.MustCompile(`^Basic ([a-zA-Z0-9\+/=]+)`) -var accessPassword string +var AccessPassword string -func isAuthorized(req *http.Request) bool { +func IsAuthorized(req *http.Request) bool { auth, present := req.Header["Authorization"] if !present { return false @@ -34,14 +34,14 @@ func isAuthorized(req *http.Request) bool { return false } password := userpass[1] // username at index 0 is currently unused - return password != "" && password == accessPassword + return password != "" && password == AccessPassword } // requireAuth wraps a function with another function that enforces // HTTP Basic Auth. -func requireAuth(handler func(conn http.ResponseWriter, req *http.Request)) func (conn http.ResponseWriter, req *http.Request) { +func RequireAuth(handler func(conn http.ResponseWriter, req *http.Request)) func (conn http.ResponseWriter, req *http.Request) { return func (conn http.ResponseWriter, req *http.Request) { - if !isAuthorized(req) { + if !IsAuthorized(req) { conn.SetHeader("WWW-Authenticate", "Basic realm=\"camlistored\"") conn.WriteHeader(http.StatusUnauthorized) fmt.Fprintf(conn, "Authentication required.\n") diff --git a/server/go/blobserver/Makefile b/server/go/blobserver/Makefile index b3267912e..9a1c26ee1 100644 --- a/server/go/blobserver/Makefile +++ b/server/go/blobserver/Makefile @@ -3,15 +3,12 @@ include $(GOROOT)/src/Make.inc TARG=camlistored GOFILES=\ camlistored.go\ - auth.go\ blobref.go\ enumerate.go\ get.go\ - http_util.go\ preupload.go\ temp_testing.go\ range.go\ upload.go\ include $(GOROOT)/src/Make.cmd - diff --git a/server/go/blobserver/camlistored.go b/server/go/blobserver/camlistored.go index f2a904a39..08592bef4 100644 --- a/server/go/blobserver/camlistored.go +++ b/server/go/blobserver/camlistored.go @@ -5,9 +5,11 @@ package main import ( + "auth" "flag" "fmt" "http" + "http_util" "os" ) @@ -17,29 +19,29 @@ var stealthMode *bool = flag.Bool("stealth", true, "Run in stealth mode.") func handleCamli(conn http.ResponseWriter, req *http.Request) { handler := func (conn http.ResponseWriter, req *http.Request) { - badRequestError(conn, "Unsupported path or method.") + http_util.BadRequestError(conn, "Unsupported path or method.") } switch req.Method { case "GET": switch req.URL.Path { case "/camli/enumerate-blobs": - handler = requireAuth(handleEnumerateBlobs) + handler = auth.RequireAuth(handleEnumerateBlobs) default: - handler = requireAuth(handleGet) + handler = auth.RequireAuth(handleGet) } case "POST": switch req.URL.Path { case "/camli/preupload": - handler = requireAuth(handlePreUpload) + handler = auth.RequireAuth(handlePreUpload) case "/camli/upload": - handler = requireAuth(handleMultiPartUpload) + handler = auth.RequireAuth(handleMultiPartUpload) case "/camli/testform": // debug only handler = handleTestForm case "/camli/form": // debug only handler = handleCamliForm } case "PUT": // no longer part of spec - handler = requireAuth(handlePut) + handler = auth.RequireAuth(handlePut) } handler(conn, req) } @@ -56,8 +58,8 @@ func handleRoot(conn http.ResponseWriter, req *http.Request) { func main() { flag.Parse() - accessPassword = os.Getenv("CAMLI_PASSWORD") - if len(accessPassword) == 0 { + auth.AccessPassword = os.Getenv("CAMLI_PASSWORD") + if len(auth.AccessPassword) == 0 { fmt.Fprintf(os.Stderr, "No CAMLI_PASSWORD environment variable set.\n") os.Exit(1) diff --git a/server/go/blobserver/get.go b/server/go/blobserver/get.go index c76a8cb29..b2ecb86fb 100644 --- a/server/go/blobserver/get.go +++ b/server/go/blobserver/get.go @@ -3,6 +3,7 @@ package main import ( "fmt" "http" + "http_util" "os" "io" ) @@ -10,7 +11,7 @@ import ( func handleGet(conn http.ResponseWriter, req *http.Request) { blobRef := ParsePath(req.URL.Path) if blobRef == nil { - badRequestError(conn, "Malformed GET URL.") + http_util.BadRequestError(conn, "Malformed GET URL.") return } fileName := blobRef.FileName() @@ -21,12 +22,12 @@ func handleGet(conn http.ResponseWriter, req *http.Request) { return } if err != nil { - serverError(conn, err) + http_util.ServerError(conn, err) return } file, err := os.Open(fileName, os.O_RDONLY, 0) if err != nil { - serverError(conn, err) + http_util.ServerError(conn, err) return } @@ -34,7 +35,7 @@ func handleGet(conn http.ResponseWriter, req *http.Request) { if reqRange.SkipBytes != 0 { _, err = file.Seek(reqRange.SkipBytes, 0) if err != nil { - serverError(conn, err) + http_util.ServerError(conn, err) return } } diff --git a/server/go/blobserver/preupload.go b/server/go/blobserver/preupload.go index 5083eb015..3e28e3790 100644 --- a/server/go/blobserver/preupload.go +++ b/server/go/blobserver/preupload.go @@ -1,22 +1,23 @@ package main import ( - "http" "container/vector" "fmt" + "http" + "http_util" "os" ) func handlePreUpload(conn http.ResponseWriter, req *http.Request) { if !(req.Method == "POST" && req.URL.Path == "/camli/preupload") { - badRequestError(conn, "Inconfigured handler.") + http_util.BadRequestError(conn, "Inconfigured handler.") return } req.ParseForm() camliVersion := req.FormValue("camliversion") if camliVersion == "" { - badRequestError(conn, "No camliversion") + http_util.BadRequestError(conn, "No camliversion") return } n := 0 @@ -31,11 +32,11 @@ func handlePreUpload(conn http.ResponseWriter, req *http.Request) { } ref := ParseBlobRef(value) if ref == nil { - badRequestError(conn, "Bogus blobref for key "+key) + http_util.BadRequestError(conn, "Bogus blobref for key "+key) return } if !ref.IsSupported() { - badRequestError(conn, "Unsupported or bogus blobref "+key) + http_util.BadRequestError(conn, "Unsupported or bogus blobref "+key) } n++ @@ -67,6 +68,6 @@ func handlePreUpload(conn http.ResponseWriter, req *http.Request) { ret := commonUploadResponse(req) ret["alreadyHave"] = haveVector.Copy() - returnJson(conn, ret) + http_util.ReturnJson(conn, ret) } diff --git a/server/go/blobserver/temp_testing.go b/server/go/blobserver/temp_testing.go index be78f7307..a0799e310 100644 --- a/server/go/blobserver/temp_testing.go +++ b/server/go/blobserver/temp_testing.go @@ -4,6 +4,7 @@ import ( "crypto/sha1" "fmt" "http" + "http_util" "io" ) @@ -27,13 +28,13 @@ Image png:
func handleTestForm(conn http.ResponseWriter, req *http.Request) { if !(req.Method == "POST" && req.URL.Path == "/camli/testform") { - badRequestError(conn, "Inconfigured handler.") + http_util.BadRequestError(conn, "Inconfigured handler.") return } multipart, err := req.MultipartReader() if multipart == nil { - badRequestError(conn, fmt.Sprintf("Expected multipart/form-data POST request; %v", err)) + http_util.BadRequestError(conn, fmt.Sprintf("Expected multipart/form-data POST request; %v", err)) return } diff --git a/server/go/blobserver/upload.go b/server/go/blobserver/upload.go index 5c1a7f61c..8817f1563 100644 --- a/server/go/blobserver/upload.go +++ b/server/go/blobserver/upload.go @@ -1,8 +1,9 @@ package main import ( - "http" "fmt" + "http" + "http_util" "io" "io/ioutil" "os" @@ -15,7 +16,7 @@ type receivedBlob struct { func handleMultiPartUpload(conn http.ResponseWriter, req *http.Request) { if !(req.Method == "POST" && req.URL.Path == "/camli/upload") { - badRequestError(conn, "Inconfigured handler.") + http_util.BadRequestError(conn, "Inconfigured handler.") return } @@ -23,7 +24,7 @@ func handleMultiPartUpload(conn http.ResponseWriter, req *http.Request) { multipart, err := req.MultipartReader() if multipart == nil { - badRequestError(conn, fmt.Sprintf( + http_util.BadRequestError(conn, fmt.Sprintf( "Expected multipart/form-data POST request; %v", err)) return } @@ -62,7 +63,7 @@ func handleMultiPartUpload(conn http.ResponseWriter, req *http.Request) { // TODO: put the blobs in the JSON here ret := commonUploadResponse(req) - returnJson(conn, ret) + http_util.ReturnJson(conn, ret) } func commonUploadResponse(req *http.Request) map[string]interface{} { @@ -132,18 +133,18 @@ func receiveBlob(blobRef *BlobRef, source io.Reader) (blobGot *receivedBlob, err func handlePut(conn http.ResponseWriter, req *http.Request) { blobRef := ParsePath(req.URL.Path) if blobRef == nil { - badRequestError(conn, "Malformed PUT URL.") + http_util.BadRequestError(conn, "Malformed PUT URL.") return } if !blobRef.IsSupported() { - badRequestError(conn, "unsupported object hash function") + http_util.BadRequestError(conn, "unsupported object hash function") return } _, err := receiveBlob(blobRef, req.Body) if err != nil { - serverError(conn, err) + http_util.ServerError(conn, err) return } diff --git a/server/go/http_util/Makefile b/server/go/http_util/Makefile new file mode 100644 index 000000000..2b74c46a3 --- /dev/null +++ b/server/go/http_util/Makefile @@ -0,0 +1,7 @@ +include $(GOROOT)/src/Make.inc + +TARG=http_util +GOFILES=\ + http_util.go + +include $(GOROOT)/src/Make.pkg diff --git a/server/go/blobserver/http_util.go b/server/go/http_util/http_util.go similarity index 62% rename from server/go/blobserver/http_util.go rename to server/go/http_util/http_util.go index ef8c687ca..e87a62433 100644 --- a/server/go/blobserver/http_util.go +++ b/server/go/http_util/http_util.go @@ -1,4 +1,4 @@ -package main +package http_util import ( "fmt" @@ -7,20 +7,20 @@ import ( "os" ) -func badRequestError(conn http.ResponseWriter, errorMessage string) { +func BadRequestError(conn http.ResponseWriter, errorMessage string) { conn.WriteHeader(http.StatusBadRequest) fmt.Fprintf(conn, "%s\n", errorMessage) } -func serverError(conn http.ResponseWriter, err os.Error) { +func ServerError(conn http.ResponseWriter, err os.Error) { conn.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(conn, "Server error: %s\n", err) } -func returnJson(conn http.ResponseWriter, data interface{}) { +func ReturnJson(conn http.ResponseWriter, data interface{}) { bytes, err := json.MarshalIndent(data, "", " ") if err != nil { - badRequestError(conn, fmt.Sprintf( + BadRequestError(conn, fmt.Sprintf( "JSON serialization error: %v", err)) return }