code: func (c *Client) doStat(ctx context.Context, blobs []blob.Ref, wait time.Duration, gated bool, fn func(blob.SizedRef) error) error {
  	var buf bytes.Buffer
  	fmt.Fprintf(&buf, "camliversion=1")
  	if wait > 0 {
  		secs := int(wait.Seconds())
  		if secs == 0 {
  			secs = 1
  		}
  		fmt.Fprintf(&buf, "&maxwaitsec=%d", secs)
  	}
  	for i, blob := range blobs {
  		fmt.Fprintf(&buf, "&blob%d=%s", i+1, blob)
  	}
  
  	pfx, err := c.prefix()
  	if err != nil {
  		return err
  	}
  	req := c.newRequest(ctx, "POST", fmt.Sprintf("%s/camli/stat", pfx), &buf)
  	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  
  	var resp *http.Response
  	if gated {
  		resp, err = c.doReqGated(req)
  	} else {
  		resp, err = c.httpClient.Do(req)
  	}
  	if err != nil {
  		return fmt.Errorf("stat HTTP error: %v", err)
  	}
  	if resp.Body != nil {
  		defer resp.Body.Close()
  	}
  
  	if resp.StatusCode != 200 {
  		return fmt.Errorf("stat response had http status %d", resp.StatusCode)
  	}
  
  	stat, err := parseStatResponse(resp)
  	if err != nil {
  		return err
  	}
  	for _, sb := range stat.HaveMap {
  		if err := fn(sb); err != nil {
  			return err
  		}
  	}
  	return nil
  }
docs: // doStat does an HTTP request for the stat. the number of blobs is used verbatim. No extra splitting
  // or batching is done at this layer.
  // The semantics are the same as blobserver.BlobStatter.
  // gate controls whether it uses httpGate to pause on requests.