Example #1
0
func (s *SlimeExt) Retrieve(e *external.External, key, file string) error {
	resp, err := http.Get(s.keyURL(key))
	if err != nil {
		return fmt.Errorf("Couldn't GET %v: %v", s.keyURL(key), err)
	}
	defer resp.Body.Close()

	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return fmt.Errorf("Couldn't GET %v: %v", resp.Request.URL, resp.Status)
	}

	fh, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
	if err != nil {
		return err
	}

	sha := sha256.New()
	reader := io.TeeReader(external.NewProgressReader(resp.Body, e), sha)
	_, err = io.Copy(fh, reader)
	if err != nil {
		fh.Close()
		return err
	}

	err = fh.Close()
	if err != nil {
		return err
	}

	if resp.Header.Get("X-Content-SHA256") != "" {
		have := sha.Sum(nil)
		want, _ := hex.DecodeString(resp.Header.Get("X-Content-SHA256"))
		if !bytes.Equal(have, want) {
			return errors.New("bad checksum of response")
		}
	}

	return nil
}
Example #2
0
func (s *SlimeExt) Store(e *external.External, key, file string) error {
	fh, err := os.Open(file)
	if err != nil {
		return err
	}
	defer fh.Close()

	shaDone := make(chan struct{})
	var sha []byte
	var length int64
	var shaError error
	go func() {
		defer close(shaDone)
		hash := sha256.New()
		length, shaError = io.Copy(hash, fh)
		if shaError != nil {
			return
		}

		sha = hash.Sum(nil)

		_, shaError = fh.Seek(0, 0)
	}()

	req, err := http.NewRequest("HEAD", s.keyURL(key), nil)
	if err != nil {
		return fmt.Errorf("Couldn't create request for %s: %v",
			s.keyURL(key), err)
	}

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return fmt.Errorf("Couldn't HEAD %v: %v", req.URL, err)
	}
	resp.Body.Close()

	<-shaDone

	if resp.StatusCode >= 200 && resp.StatusCode < 300 {
		if oldSHA := resp.Header.Get("X-Content-SHA256"); oldSHA != "" {
			if strings.ToLower(oldSHA) == hex.EncodeToString(sha) {
				// Key already exists with the correct data
				return nil
			}
		}
	}

	req, err = http.NewRequest("PUT", s.keyURL(key),
		external.NewProgressReader(fh, e))
	if err != nil {
		return fmt.Errorf("Couldn't create request for %s: %v",
			s.keyURL(key), err)
	}
	req.Header.Set("X-Content-SHA256", hex.EncodeToString(sha))
	req.Header.Set("Content-Length", strconv.FormatInt(length, 10))

	resp, err = http.DefaultClient.Do(req)
	if err != nil {
		return fmt.Errorf("Couldn't PUT to %v: %v", req.URL, err)
	}
	resp.Body.Close()

	if resp.StatusCode < 200 || resp.StatusCode >= 300 {
		return fmt.Errorf("Couldn't PUT to %v: %v", req.URL, resp.Status)
	}

	return nil
}