func (c *Client) Do(req *http.Request) (*http.Response, error) {
	return c.do(contextFromRequest(req), req, nil)
}
Do is like DoWithContext, except the context is automatically derived.
If using go version 1.7 or later the context will be taken from the
given request, otherwise context.Background() will be used.
package httpbakery
import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"strings"
	"time"
	"golang.org/x/net/context"
	"golang.org/x/net/context/ctxhttp"
	"golang.org/x/net/publicsuffix"
	"gopkg.in/errgo.v1"
	"gopkg.in/httprequest.v1"
	"gopkg.in/macaroon.v2"
	"gopkg.in/macaroon-bakery.v2/bakery"
	"gopkg.in/macaroon-bakery.v2/bakery/checkers"
)
var unmarshalError = httprequest.ErrorUnmarshaler(&Error{})
const maxDischargeRetries = 3
type DischargeError struct {
	Reason *Error
}
func (e *DischargeError) Error() string {
	return fmt.Sprintf("third party refused discharge: %v", e.Reason)
}
func IsDischargeError(err error) bool {
	_, ok := err.(*DischargeError)
	return ok
}
type InteractionError struct {
	Reason error
}
func (e *InteractionError) Error() string {
	return fmt.Sprintf("cannot start interactive session: %v", e.Reason)
}
func IsInteractionError(err error) bool {
	_, ok := err.(*InteractionError)
	return ok
}
func NewHTTPClient() *http.Client {
	c := *http.DefaultClient
	c.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		if len(via) >= 10 {
			return fmt.Errorf("too many redirects")
		}
		if len(via) == 0 {
			return nil
		}
		for attr, val := range via[0].Header {
			if attr == "Cookie" {
				continue
			}
			if _, ok := req.Header[attr]; !ok {
				req.Header[attr] = val
			}
		}
		return nil
	}
	jar, err := cookiejar.New(&cookiejar.Options{
		PublicSuffixList: publicsuffix.List,
	})
	if err != nil {
		panic(err)
	}
	c.Jar = jar
	return &c
}
type Client struct {
	*http.Client
	InteractionMethods []Interactor
	Key *bakery.KeyPair
	Logger bakery.Logger
}
type Interactor interface {
	Kind() string
	Interact(ctx context.Context, client *Client, location string, interactionRequiredErr *Error) (*DischargeToken, error)
}
type DischargeToken struct {
	Kind string `json:"kind"`
	Value []byte `json:"value"`
}
type LegacyInteractor interface {
	LegacyInteract(ctx context.Context, client *Client, location string, visitURL *url.URL) error
}
func NewClient() *Client {
	return &Client{
		Client: NewHTTPClient(),
	}
}
func (c *Client) AddInteractor(i Interactor) {
	c.InteractionMethods = append(c.InteractionMethods, i)
}
func (c *Client) DischargeAll(ctx context.Context, m *bakery.Macaroon) (macaroon.Slice, error) {
	return bakery.DischargeAllWithKey(ctx, m, c.AcquireDischarge, c.Key)
}
func (c *Client) DischargeAllUnbound(ctx context.Context, ms bakery.Slice) (bakery.Slice, error) {
	return ms.DischargeAll(ctx, c.AcquireDischarge, c.Key)
}