code: func (f *httpFetcher) Hash(u *url.URL, a *asc) (string, error) {
  	ensureLogger(f.Debug)
  	urlStr := u.String()
  
  	if !f.NoCache && f.Rem != nil {
  		if useCached(f.Rem.DownloadTime, f.Rem.CacheMaxAge) {
  			diag.Printf("image for %s isn't expired, not fetching.", urlStr)
  			return f.Rem.BlobKey, nil
  		}
  	}
  
  	diag.Printf("fetching image from %s", urlStr)
  
  	aciFile, cd, err := f.fetchURL(u, a, eTag(f.Rem))
  	if err != nil {
  		return "", err
  	}
  	defer aciFile.Close()
  
  	if key := maybeUseCached(f.Rem, cd); key != "" {
  		// TODO(krnowak): that does not update the store with
  		// the new CacheMaxAge and Download Time, so it will
  		// query the server every time after initial
  		// CacheMaxAge is exceeded
  		return key, nil
  	}
  	key, err := f.S.WriteACI(aciFile, imagestore.ACIFetchInfo{
  		Latest: false,
  	})
  	if err != nil {
  		return "", err
  	}
  
  	// TODO(krnowak): What's the point of the second parameter?
  	// The SigURL field in imagestore.Remote seems to be completely
  	// unused.
  	newRem := imagestore.NewRemote(urlStr, a.Location)
  	newRem.BlobKey = key
  	newRem.DownloadTime = time.Now()
  	if cd != nil {
  		newRem.ETag = cd.ETag
  		newRem.CacheMaxAge = cd.MaxAge
  	}
  	err = f.S.WriteRemote(newRem)
  	if err != nil {
  		return "", err
  	}
  
  	return key, nil
  }
docs: // Hash fetches the URL, optionally verifies it against passed asc,
  // stores it in the store and returns the hash.