Skip to content

Commit

Permalink
Add debug logging mode (B2_DEBUG=1)
Browse files Browse the repository at this point in the history
Take the occasion to move Authorization into the RoundTripper.

Use build tags to only enable httptrace on Go 1.7.
  • Loading branch information
FiloSottile committed Oct 30, 2016
1 parent 0272537 commit 6a0843a
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 38 deletions.
69 changes: 56 additions & 13 deletions b2.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
//
// Large files (b2_*_large_file, b2_*_part), b2_get_download_authorization,
// b2_hide_file, b2_update_bucket.
//
// Debug mode
//
// If the B2_DEBUG environment variable is set to 1, all API calls will be
// logged. On Go 1.7 and later, it will also log when new (non-reused)
// connections are established.
package b2

import (
Expand All @@ -38,7 +44,9 @@ import (
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"sync"
)

Expand Down Expand Up @@ -94,6 +102,7 @@ func NewClient(accountID, applicationKey string, httpClient *http.Client) (*Clie
return nil, err
}
defer drainAndClose(res.Body)
debugf("login: %d", res.StatusCode)

if res.StatusCode != 200 {
b2Err := &Error{}
Expand All @@ -104,6 +113,7 @@ func NewClient(accountID, applicationKey string, httpClient *http.Client) (*Clie
}

c := &Client{hc: httpClient}
c.hc.Transport = &transport{t: c.hc.Transport, c: c}
if err := json.NewDecoder(res.Body).Decode(c); err != nil {
return nil, fmt.Errorf("failed to decode b2_authorize_account answer: %s", err)
}
Expand All @@ -120,28 +130,61 @@ func NewClient(accountID, applicationKey string, httpClient *http.Client) (*Clie
return c, nil
}

func (c *Client) doRequest(endpoint string, params map[string]interface{}) (*http.Response, error) {
body, err := json.Marshal(params)
if err != nil {
return nil, err
// transport is a wrapper providing authentication, tracing and error handling.
type transport struct {
t http.RoundTripper
c *Client
}

// requestExtFunc is implemented in the go1.7 file, to add httptrace
var requestExtFunc func(*http.Request) *http.Request

func (t *transport) RoundTrip(req *http.Request) (res *http.Response, err error) {
if req.Header.Get("Authorization") == "" {
req.Header.Set("Authorization", t.c.AuthorizationToken)
}

r, err := http.NewRequest("POST", c.ApiURL+apiPath+endpoint, bytes.NewBuffer(body))
if err != nil {
return nil, err
if requestExtFunc != nil {
req = requestExtFunc(req)
}
r.Header.Set("Authorization", c.AuthorizationToken)

res, err := c.hc.Do(r)
if err != nil {
return nil, err
if t.t == nil {
res, err = http.DefaultTransport.RoundTrip(req)
} else {
res, err = t.t.RoundTrip(req)
}

if res.StatusCode != 200 {
if err == nil && res.StatusCode != 200 {
return nil, parseB2Error(res)
}

return res, nil
return res, err
}

var debug = os.Getenv("B2_DEBUG") == "1"

func debugf(format string, a ...interface{}) {
if debug {
log.Printf("[b2] "+format, a...)
}
}

func (c *Client) doRequest(endpoint string, params map[string]interface{}) (*http.Response, error) {
body, err := json.Marshal(params)
if err != nil {
return nil, err
}
// Reduce debug log noise
delete(params, "accountID")
delete(params, "bucketID")

res, err := c.hc.Post(c.ApiURL+apiPath+endpoint, "application/json", bytes.NewBuffer(body))
if err != nil {
debugf("%s (%v): %v", endpoint, params, err)
} else {
debugf("%s (%v)", endpoint, params)
}
return res, err
}

func parseB2Error(res *http.Response) error {
Expand Down
21 changes: 21 additions & 0 deletions b2_go17.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// +build go1.7

package b2

import (
"net/http"
"net/http/httptrace"
)

func addTracing(req *http.Request) *http.Request {
trace := &httptrace.ClientTrace{
ConnectStart: func(network, addr string) {
debugf("new connection to %s (for %s)", addr, req.URL.Path)
},
}
return req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
}

func init() {
requestExtFunc = addTracing
}
28 changes: 6 additions & 22 deletions download.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,12 @@ import (
// Note: the (*FileInfo).CustomMetadata values returned by this function are
// all represented as strings, because they are delivered by HTTP headers.
func (c *Client) DownloadFileByID(id string) (io.ReadCloser, *FileInfo, error) {
url := c.DownloadURL + apiPath + "b2_download_file_by_id?fileId=" + id
r, err := http.NewRequest("GET", url, nil)
res, err := c.hc.Get(c.DownloadURL + apiPath + "b2_download_file_by_id?fileId=" + id)
if err != nil {
debugf("download %s: %s", id, err)
return nil, nil, err
}
r.Header.Set("Authorization", c.AuthorizationToken)

res, err := c.hc.Do(r)
if err != nil {
return nil, nil, err
}
if res.StatusCode != 200 {
return nil, nil, parseB2Error(res)
}
debugf("download %s (%s)", id, res.Header.Get("X-Bz-Content-Sha1"))

fi, err := parseFileInfoHeaders(res.Header)
return res.Body, fi, err
Expand All @@ -39,20 +31,12 @@ func (c *Client) DownloadFileByID(id string) (io.ReadCloser, *FileInfo, error) {
// Note: the (*FileInfo).CustomMetadata values returned by this function are
// all represented as strings, because they are delivered by HTTP headers.
func (c *Client) DownloadFileByName(bucket, file string) (io.ReadCloser, *FileInfo, error) {
url := c.DownloadURL + "/file/" + bucket + "/" + file
r, err := http.NewRequest("GET", url, nil)
res, err := c.hc.Get(c.DownloadURL + "/file/" + bucket + "/" + file)
if err != nil {
debugf("download %s: %s", file, err)
return nil, nil, err
}
r.Header.Set("Authorization", c.AuthorizationToken)

res, err := c.hc.Do(r)
if err != nil {
return nil, nil, err
}
if res.StatusCode != 200 {
return nil, nil, parseB2Error(res)
}
debugf("download %s (%s)", file, res.Header.Get("X-Bz-Content-Sha1"))

fi, err := parseFileInfoHeaders(res.Header)
return res.Body, fi, err
Expand Down
6 changes: 3 additions & 3 deletions upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func (b *Bucket) Upload(r io.Reader, name, mimeType string) (*FileInfo, error) {
case io.ReadSeeker:
body = r
default:
debugf("upload %s: buffering", name)
b, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
Expand Down Expand Up @@ -122,11 +123,10 @@ func (b *Bucket) UploadWithSHA1(r io.Reader, name, mimeType, sha1Sum string, len

res, err := b.c.hc.Do(req)
if err != nil {
debugf("upload %s: %s", name, err)
return nil, err
}
if res.StatusCode != 200 {
return nil, parseB2Error(res)
}
debugf("upload %s (%d %s)", name, length, sha1Sum)
defer drainAndClose(res.Body)

fi := fileInfoObj{}
Expand Down

0 comments on commit 6a0843a

Please sign in to comment.