func (c *Client) Do(req *http.Request, v io.Writer) (*Response, error) {
	var keep, send io.ReadCloser
	if req.Body != nil {
		if buf, err := ioutil.ReadAll(req.Body); err == nil {
			keep = ioutil.NopCloser(bytes.NewReader(buf))
			send = ioutil.NopCloser(bytes.NewReader(buf))
			req.Body = send
		}
	}
	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	response := newResponse(resp)
	if keep != nil {
		req.Body = keep
	}
	err = getError(resp, req)
	if err != nil {
		return response, err
	}
	if v != nil {
		io.Copy(v, resp.Body)
	}
	return response, nil
}
Do executes requests to the server.

The response body is copied into v if v is not nil.
Returns a *Response that wraps the http.Response returned from the server.
The response body is available in the *Response in case the consumer wishes
to process it in some way rather than read if from the argument v
package goes
import (
	"bytes"
	"encoding/json"
	"encoding/xml"
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"github.com/jetbasrawi/go.geteventstore/atom"
)
type Response struct {
	*http.Response
	Status     string
	StatusCode int
}
type ErrorResponse struct {
	*http.Response
	Request    *http.Request
	Status     string
	StatusCode int
}
func (r *ErrorResponse) Error() string {
	return fmt.Sprintf("%v %v: %d %+v",
		r.Response.Request.Method, r.Response.Request.URL,
		r.Response.StatusCode, r.Status)
}
type basicAuthCredentials struct {
	Username string
	Password string
}
type Client struct {
	client      *http.Client
	baseURL     *url.URL
	credentials *basicAuthCredentials
	headers     map[string]string
}
func NewClient(httpClient *http.Client, serverURL string) (*Client, error) {
	if httpClient == nil {
		httpClient = http.DefaultClient
	}
	baseURL, err := url.Parse(serverURL)
	if err != nil {
		return nil, err
	}
	c := &Client{
		client:  httpClient,
		baseURL: baseURL,
		headers: make(map[string]string),
	}
	return c, nil
}
func (c *Client) copy() *Client {
	client := &Client{
		client:      c.client,
		baseURL:     c.baseURL,
		credentials: c.credentials,
		headers:     make(map[string]string),
	}
	for k, v := range c.headers {
		client.headers[k] = v
	}
	return client
}
func (c *Client) NewStreamReader(streamName string) *StreamReader {
	sr := &StreamReader{
		streamName: streamName,
		client:     c.copy(),
		version:    -1,
		pageSize:   20,
	}
	sr.LongPoll(-1)
	return sr
}
func (c *Client) NewStreamWriter(streamName string) *StreamWriter {
	return &StreamWriter{
		client:     c,
		streamName: streamName,
	}
}
func (c *Client) SetBasicAuth(username, password string) {
	c.credentials = &basicAuthCredentials{
		Username: username,
		Password: password,
	}
}
func (c *Client) GetEvent(url string) (*EventResponse, *Response, error) {
	r, err := c.NewRequest("GET", url, nil)
	if err != nil {
		return nil, nil, err
	}
	r.Header.Set("Accept", "application/vnd.eventstore.atom+json")
	var b bytes.Buffer
	resp, err := c.Do(r, &b)
	if err != nil {
		return nil, resp, err
	}
	if b.String() == "{}" {
		return nil, resp, nil
	}
	var raw json.RawMessage
	er := &EventAtomResponse{Content: &raw}
	err = json.NewDecoder(bytes.NewReader(b.Bytes())).Decode(er)
	if err == io.EOF {
		return nil, resp, nil
	}
	if err != nil {
		return nil, resp, err
	}
	var d json.RawMessage
	var m json.RawMessage
	ev := &Event{Data: &d, MetaData: &m}
	err = json.Unmarshal(raw, ev)
	if err == io.EOF {
		err = nil
	}
	if err != nil {
		return nil, resp, err
	}
	e := EventResponse{}
	e.Title = er.Title
	e.ID = er.ID
	e.Updated = er.Updated
	e.Summary = er.Summary
	e.Event = ev
	return &e, resp, nil
}
func (c *Client) ReadFeed(url string) (*atom.Feed, *Response, error) {
	req, err := c.NewRequest("GET", url, nil)
	if err != nil {
		return nil, nil, err
	}
	req.Header.Set("Accept", "application/atom+xml")
	var b bytes.Buffer
	resp, err := c.Do(req, &b)
	if err != nil {
		return nil, resp, err
	}
	feed := &atom.Feed{}
	err = xml.NewDecoder(bytes.NewReader(b.Bytes())).Decode(feed)
	if err != nil {
		return nil, resp, err
	}
	return feed, resp, nil
}
func (c *Client) GetFeedPath(stream, direction string, version int, pageSize int) (string, error) {
	ps := pageSize
	dir := ""
	switch direction {
	case "forward", "backward":
		dir = direction
	default:
		return "", fmt.Errorf("Invalid Direction %s. Allowed values are \"forward\" or \"backward\" \n", direction)
	}
	v := "head"
	if version >= 0 {
		v = strconv.Itoa(version)
	}
	if v == "head" && dir == "forward" {
		return "", fmt.Errorf("Invalid Direction (%s) and version (head) combination.\n", direction)
	}
	return fmt.Sprintf("/streams/%s/%s/%s/%d", stream, v, dir, ps), nil
}
func (c *Client) GetMetadataURL(stream string) (string, *Response, error) {
	url, err := c.GetFeedPath(stream, "forward", 0, 1)
	if err != nil {
		return "", nil, err
	}
	f, resp, err := c.ReadFeed(url)
	if err != nil {
		return "", resp, err
	}
	for _, v := range f.Link {
		if v.Rel == "metadata" {
			return v.Href, resp, nil
		}
	}
	return "", resp, nil
}
func (c *Client) SetHeader(key, value string) {
	c.headers[key] = value
}
func (c *Client) DeleteHeader(key string) {
	delete(c.headers, key)
}
func (c *Client) DeleteStream(streamName string, hardDelete bool) (*Response, error) {
	url := fmt.Sprintf("/streams/%s", streamName)
	req, err := c.NewRequest(http.MethodDelete, url, nil)
	if err != nil {
		return nil, err
	}
	if hardDelete {
		req.Header.Set("ES-HardDelete", "true")
	}
	resp, err := c.Do(req, nil)
	if err != nil {
		return resp, err
	}
	return resp, nil
}
func (c *Client) NewRequest(method, urlString string, body interface{}) (*http.Request, error) {
	url, err := url.Parse(urlString)
	if err != nil {
		return nil, err
	}
	if !url.IsAbs() {
		url = c.baseURL.ResolveReference(url)
	}
	var buf io.ReadWriter
	if body != nil {
		buf = new(bytes.Buffer)
		err := json.NewEncoder(buf).Encode(body)
		if err != nil {
			return nil, err
		}
	}
	req, err := http.NewRequest(method, url.String(), buf)
	if err != nil {
		return nil, err
	}
	if c.credentials != nil {
		req.SetBasicAuth(c.credentials.Username, c.credentials.Password)
	}
	for k, v := range c.headers {
		req.Header.Set(k, v)
	}
	return req, nil
}