X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/682dd5b6cc23a455766a7651e3e841257660b31c..a1819526b85ce37c7d3ae421c2f5329c1c245c7f:/services/keepstore/handlers.go diff --git a/services/keepstore/handlers.go b/services/keepstore/handlers.go index cf5dfcac57..3898b55b61 100644 --- a/services/keepstore/handlers.go +++ b/services/keepstore/handlers.go @@ -19,9 +19,7 @@ import ( "net/http" "os" "regexp" - "runtime" "strconv" - "strings" "syscall" "time" ) @@ -67,51 +65,15 @@ func BadRequestHandler(w http.ResponseWriter, r *http.Request) { } func GetBlockHandler(resp http.ResponseWriter, req *http.Request) { - hash := mux.Vars(req)["hash"] - - hints := mux.Vars(req)["hints"] - - // Parse the locator string and hints from the request. - // TODO(twp): implement a Locator type. - var signature, timestamp string - if hints != "" { - signature_pat, _ := regexp.Compile("^A([[:xdigit:]]+)@([[:xdigit:]]{8})$") - for _, hint := range strings.Split(hints, "+") { - if match, _ := regexp.MatchString("^[[:digit:]]+$", hint); match { - // Server ignores size hints - } else if m := signature_pat.FindStringSubmatch(hint); m != nil { - signature = m[1] - timestamp = m[2] - } else if match, _ := regexp.MatchString("^[[:upper:]]", hint); match { - // Any unknown hint that starts with an uppercase letter is - // presumed to be valid and ignored, to permit forward compatibility. - } else { - // Unknown format; not a valid locator. - http.Error(resp, BadRequestError.Error(), BadRequestError.HTTPCode) - return - } - } - } - - // If permission checking is in effect, verify this - // request's permission signature. if enforce_permissions { - if signature == "" || timestamp == "" { - http.Error(resp, PermissionError.Error(), PermissionError.HTTPCode) - return - } else if IsExpired(timestamp) { - http.Error(resp, ExpiredError.Error(), ExpiredError.HTTPCode) + locator := req.URL.Path[1:] // strip leading slash + if err := VerifySignature(locator, GetApiToken(req)); err != nil { + http.Error(resp, err.Error(), err.(*KeepError).HTTPCode) return - } else { - req_locator := req.URL.Path[1:] // strip leading slash - if !VerifySignature(req_locator, GetApiToken(req)) { - http.Error(resp, PermissionError.Error(), PermissionError.HTTPCode) - return - } } } - block, err := GetBlock(hash, false) + block, err := GetBlock(mux.Vars(req)["hash"], false) if err != nil { // This type assertion is safe because the only errors // GetBlock can return are DiskHashError or NotFoundError. @@ -126,10 +88,6 @@ func GetBlockHandler(resp http.ResponseWriter, req *http.Request) { } func PutBlockHandler(resp http.ResponseWriter, req *http.Request) { - // Garbage collect after each PUT. Fixes #2865. - // See also GetBlockHandler. - defer runtime.GC() - hash := mux.Vars(req)["hash"] // Detect as many error conditions as possible before reading @@ -203,6 +161,9 @@ func IndexHandler(resp http.ResponseWriter, req *http.Request) { return } } + // An empty line at EOF is the only way the client can be + // assured the entire index was received. + resp.Write([]byte{'\n'}) } // StatusHandler @@ -525,6 +486,7 @@ func GetBlock(hash string, update_timestamp bool) ([]byte, error) { log.Printf("%s: checksum mismatch for request %s (actual %s)\n", vol, hash, filehash) error_to_caller = DiskHashError + bufs.Put(buf) continue } if error_to_caller == DiskHashError { @@ -536,6 +498,7 @@ func GetBlock(hash string, update_timestamp bool) ([]byte, error) { error_to_caller = GenericError log.Printf("%s: Touch %s failed: %s", vol, hash, error_to_caller) + bufs.Put(buf) continue } } @@ -586,6 +549,7 @@ func PutBlock(block []byte, hash string) error { // so there is nothing special to do if err != nil. // if oldblock, err := GetBlock(hash, true); err == nil { + defer bufs.Put(oldblock) if bytes.Compare(block, oldblock) == 0 { // The block already exists; return success. return nil @@ -632,28 +596,25 @@ func PutBlock(block []byte, hash string) error { } } +var validLocatorRe = regexp.MustCompile(`^[0-9a-f]{32}$`) + // IsValidLocator // Return true if the specified string is a valid Keep locator. // When Keep is extended to support hash types other than MD5, // this should be updated to cover those as well. // func IsValidLocator(loc string) bool { - match, err := regexp.MatchString(`^[0-9a-f]{32}$`, loc) - if err == nil { - return match - } - log.Printf("IsValidLocator: %s\n", err) - return false + return validLocatorRe.MatchString(loc) } +var authRe = regexp.MustCompile(`^OAuth2\s+(.*)`) + // GetApiToken returns the OAuth2 token from the Authorization // header of a HTTP request, or an empty string if no matching // token is found. func GetApiToken(req *http.Request) string { if auth, ok := req.Header["Authorization"]; ok { - if pat, err := regexp.Compile(`^OAuth2\s+(.*)`); err != nil { - log.Println(err) - } else if match := pat.FindStringSubmatch(auth[0]); match != nil { + if match := authRe.FindStringSubmatch(auth[0]); match != nil { return match[1] } }