Example #1
0
func (this PutBlockHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {

	kc := *this.KeepClient

	hash := mux.Vars(req)["hash"]
	hints := mux.Vars(req)["hints"]

	locator := keepclient.MakeLocator2(hash, hints)

	var contentLength int64 = -1
	if req.Header.Get("Content-Length") != "" {
		_, err := fmt.Sscanf(req.Header.Get("Content-Length"), "%d", &contentLength)
		if err != nil {
			resp.Header().Set("Content-Length", fmt.Sprintf("%d", contentLength))
		}

	}

	log.Printf("%s: %s %s Content-Length %v", GetRemoteAddress(req), req.Method, hash, contentLength)

	if contentLength < 1 {
		http.Error(resp, "Must include Content-Length header", http.StatusLengthRequired)
		return
	}

	if locator.Size > 0 && int64(locator.Size) != contentLength {
		http.Error(resp, "Locator size hint does not match Content-Length header", http.StatusBadRequest)
		return
	}

	var pass bool
	var tok string
	if pass, tok = CheckAuthorizationHeader(kc, this.ApiTokenCache, req); !pass {
		http.Error(resp, "Missing or invalid Authorization header", http.StatusForbidden)
		return
	}

	// Copy ArvadosClient struct and use the client's API token
	arvclient := *kc.Arvados
	arvclient.ApiToken = tok
	kc.Arvados = &arvclient

	// Check if the client specified the number of replicas
	if req.Header.Get("X-Keep-Desired-Replicas") != "" {
		var r int
		_, err := fmt.Sscanf(req.Header.Get(keepclient.X_Keep_Desired_Replicas), "%d", &r)
		if err != nil {
			kc.Want_replicas = r
		}
	}

	// Now try to put the block through
	hash, replicas, err := kc.PutHR(hash, req.Body, contentLength)

	// Tell the client how many successful PUTs we accomplished
	resp.Header().Set(keepclient.X_Keep_Replicas_Stored, fmt.Sprintf("%d", replicas))

	switch err {
	case nil:
		// Default will return http.StatusOK
		log.Printf("%s: %s %s finished, stored %v replicas (desired %v)", GetRemoteAddress(req), req.Method, hash, replicas, kc.Want_replicas)
		n, err2 := io.WriteString(resp, hash)
		if err2 != nil {
			log.Printf("%s: wrote %v bytes to response body and got error %v", n, err2.Error())
		}

	case keepclient.OversizeBlockError:
		// Too much data
		http.Error(resp, fmt.Sprintf("Exceeded maximum blocksize %d", keepclient.BLOCKSIZE), http.StatusRequestEntityTooLarge)

	case keepclient.InsufficientReplicasError:
		if replicas > 0 {
			// At least one write is considered success.  The
			// client can decide if getting less than the number of
			// replications it asked for is a fatal error.
			// Default will return http.StatusOK
			n, err2 := io.WriteString(resp, hash)
			if err2 != nil {
				log.Printf("%s: wrote %v bytes to response body and got error %v", n, err2.Error())
			}
		} else {
			http.Error(resp, "", http.StatusServiceUnavailable)
		}

	default:
		http.Error(resp, err.Error(), http.StatusBadGateway)
	}

	if err != nil {
		log.Printf("%s: %s %s stored %v replicas (desired %v) got error %v", GetRemoteAddress(req), req.Method, hash, replicas, kc.Want_replicas, err.Error())
	}

}
Example #2
0
func (this GetBlockHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {

	kc := *this.KeepClient

	hash := mux.Vars(req)["hash"]
	hints := mux.Vars(req)["hints"]

	locator := keepclient.MakeLocator2(hash, hints)

	log.Printf("%s: %s %s", GetRemoteAddress(req), req.Method, hash)

	var pass bool
	var tok string
	if pass, tok = CheckAuthorizationHeader(kc, this.ApiTokenCache, req); !pass {
		http.Error(resp, "Missing or invalid Authorization header", http.StatusForbidden)
		return
	}

	// Copy ArvadosClient struct and use the client's API token
	arvclient := *kc.Arvados
	arvclient.ApiToken = tok
	kc.Arvados = &arvclient

	var reader io.ReadCloser
	var err error
	var blocklen int64

	if req.Method == "GET" {
		reader, blocklen, _, err = kc.AuthorizedGet(hash, locator.Signature, locator.Timestamp)
		defer reader.Close()
	} else if req.Method == "HEAD" {
		blocklen, _, err = kc.AuthorizedAsk(hash, locator.Signature, locator.Timestamp)
	}

	if blocklen > 0 {
		resp.Header().Set("Content-Length", fmt.Sprint(blocklen))
	}

	switch err {
	case nil:
		if reader != nil {
			n, err2 := io.Copy(resp, reader)
			if n != blocklen {
				log.Printf("%s: %s %s mismatched return %v with Content-Length %v error %v", GetRemoteAddress(req), req.Method, hash, n, blocklen, err2)
			} else if err2 == nil {
				log.Printf("%s: %s %s success returned %v bytes", GetRemoteAddress(req), req.Method, hash, n)
			} else {
				log.Printf("%s: %s %s returned %v bytes error %v", GetRemoteAddress(req), req.Method, hash, n, err.Error())
			}
		} else {
			log.Printf("%s: %s %s success", GetRemoteAddress(req), req.Method, hash)
		}
	case keepclient.BlockNotFound:
		http.Error(resp, "Not found", http.StatusNotFound)
	default:
		http.Error(resp, err.Error(), http.StatusBadGateway)
	}

	if err != nil {
		log.Printf("%s: %s %s error %s", GetRemoteAddress(req), req.Method, hash, err.Error())
	}
}