"Overload" http.Client's Get method

627 views
Skip to first unread message

BeMasher

unread,
Nov 10, 2012, 9:03:07 AM11/10/12
to golan...@googlegroups.com
I'm working on a project which uses the OAuth (code.google.com/p/goauth2/oauth) and Google Calendar API (code.google.com/p/google-api-go-client/calendar/v3) packages to automatically create new events on a particular calendar. However I'm running into some issues with the OAuth package failing certain operations related to http.

Once authenticated with OAuth an http.Client is generated to use with with any requests made to Google API's that support OAuth authentication. I'm having some issues on my linux system with certain http operations failing in the OAuth package and I want to "overload" the Get method on the http.Client passed to the calendar service to write out diagnostics to a log file.

What I want to do is "overload" the Get method of the http.Client that is given to the calendar service to include some logging so I can see what requests are being made and what their contents are. I'm not exactly sure how to go about doing this. I've tried embedding the http.Client into a new type and calling the embedded Get method before dumping the response to a log file, but I can't pass this type to the calendar service initialization method because it only accepts http.Client.

Am I thinking about this the right way and just missing some caveat or am I going the complete wrong direction?

BeMasher

unread,
Nov 10, 2012, 9:05:10 AM11/10/12
to golan...@googlegroups.com
Whoops, meant: code.google.com/p/goauth2

Rémy Oudompheng

unread,
Nov 10, 2012, 9:20:57 AM11/10/12
to BeMasher, golan...@googlegroups.com
On 2012/11/10 BeMasher <bema...@gmail.com> wrote:
> On Saturday, November 10, 2012 7:03:07 AM UTC-7, BeMasher wrote:
>>
>> I'm working on a project which uses the OAuth
>> (code.google.com/p/goauth2/oauth) and Google Calendar API
>> (code.google.com/p/google-api-go-client/calendar/v3) packages to
>> automatically create new events on a particular calendar. However I'm
>> running into some issues with the OAuth package failing certain operations
>> related to http.
>>
>> Once authenticated with OAuth an http.Client is generated to use with with
>> any requests made to Google API's that support OAuth authentication. I'm
>> having some issues on my linux system with certain http operations failing
>> in the OAuth package and I want to "overload" the Get method on the
>> http.Client passed to the calendar service to write out diagnostics to a log
>> file.
>>
>> What I want to do is "overload" the Get method of the http.Client that is
>> given to the calendar service to include some logging so I can see what
>> requests are being made and what their contents are.

You can override the Transport field of http.Client to instrument the
connections and sniff the traffic.

Rémy.

Jesse McNelis

unread,
Nov 10, 2012, 9:21:35 AM11/10/12
to BeMasher, golang-nuts
What I want to do is "overload" the Get method of the http.Client that is given to the calendar service to include some logging so I can see what requests are being made and what their contents are. I'm not exactly sure how to go about doing this. I've tried embedding the http.Client into a new type and calling the embedded Get method before dumping the response to a log file, but I can't pass this type to the calendar service initialization method because it only accepts http.Client.

Yep, you can't override the Get() method on a type you didn't create and can't pass something that isn't a http.Client to something that expects a http.Client and since http.Client isn't an interface you can't make your own implementation of it.

Luckily the http.Client has a field called 'Transport' that is of type RoundTripper and RoundTripper is an interface type.
All requests through the http.Client go through the RoundTripper so if you create your own type that satisfies the RoundTripper interface and put it in the http.Client you can intercept any requests it does.

The default round tripper implementation is http://golang.org/pkg/net/http/#Transport so just embed that in a type and add your own 
RoundTrip(*Request) (*Response, error) to wrap Transport's one. eg.

type MyTransport {
    http.Transport
}

func (m *MyTransport) RoundTrip(r *Request) (*Response, error){
    log.Println(r.URL)
    return m.Transport.RoundTrip(r)
}

--
=====================
http://jessta.id.au


BeMasher

unread,
Nov 11, 2012, 6:28:20 AM11/11/12
to golan...@googlegroups.com, BeMasher, jes...@jessta.id.au
Perfect, just what I was looking for.

type TransportLogger struct {
http.RoundTripper
}

func (lt TransportLogger) RoundTrip(r *http.Request) (res *http.Response, err error) {
log.Println("Getting:", r.URL)
res, err = lt.RoundTripper.RoundTrip(r)
data, dumpErr := httputil.DumpResponse(res, false)
errhandler.Handle("Error dumping response: ", dumpErr)
log.Printf("Response: %s\n", data)
return
}
Reply all
Reply to author
Forward
0 new messages