code: func (r *Request) Do(c context.Context) error {
  	// Grab a client first. Use same client for all retry attempts.
  	var client *http.Client
  	if clientFactory != nil {
  		var err error
  		if client, err = clientFactory(c, r.Scopes); err != nil {
  			return err
  		}
  	} else {
  		client = http.DefaultClient
  		if testTransport := c.Value(&testTransportKey); testTransport != nil {
  			client = &http.Client{Transport: testTransport.(http.RoundTripper)}
  		}
  	}
  
  	// Prepare a blob with the request body. Marshal it once, to avoid
  	// remarshaling on retries.
  	isJSON := false
  	var bodyBlob []byte
  	if blob, ok := r.Body.([]byte); ok {
  		bodyBlob = blob
  	} else if r.Body != nil {
  		var err error
  		if bodyBlob, err = json.Marshal(r.Body); err != nil {
  			return err
  		}
  		isJSON = true
  	}
  
  	return fetchJSON(c, client, r.Out, func() (*http.Request, error) {
  		req, err := http.NewRequest(r.Method, r.URL, bytes.NewReader(bodyBlob))
  		if err != nil {
  			return nil, err
  		}
  		for k, v := range r.Headers {
  			req.Header.Set(k, v)
  		}
  		if isJSON {
  			req.Header.Set("Content-Type", "application/json")
  		}
  		return req, nil
  	})
  }
docs: // Do performs an HTTP request with retries on transient errors.
  //
  // It can be used to make GET or DELETE requests (if Body is nil) or POST or PUT
  // requests (if Body is not nil). In latter case the body will be serialized to
  // JSON.
  //
  // Respects context's deadline and cancellation.