From bce6ba765a3be25fa13fc602e42398b682564913 Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Tue, 2 Oct 2018 16:07:29 +0200 Subject: [PATCH] Allow customizing the protocol tag for each RoundTripper This adds optional functional Options to the NewTransport method. --- p2phttp.go | 59 ++++++++++++++++++++++++++++++++++--------------- p2phttp_test.go | 4 ++-- 2 files changed, 43 insertions(+), 20 deletions(-) diff --git a/p2phttp.go b/p2phttp.go index 1b44353..ffd4121 100644 --- a/p2phttp.go +++ b/p2phttp.go @@ -57,14 +57,51 @@ import ( protocol "github.com/libp2p/go-libp2p-protocol" ) -// P2PProtocol is used to tag and identify streams +// DefaultP2PProtocol is used to tag and identify streams // handled by go-libp2p-http -var P2PProtocol protocol.ID = "/libp2p-http" +var DefaultP2PProtocol protocol.ID = "/libp2p-http" + +// options holds configuration options for the transport. +type options struct { + Protocol protocol.ID +} + +// Option allows to set the libp2p transport options. +type Option func(o *options) + +// ProtocolOption sets the Protocol Tag associated to the libp2p roundtripper. +func ProtocolOption(p protocol.ID) Option { + return func(o *options) { + o.Protocol = p + } +} // RoundTripper implemenets http.RoundTrip and can be used as // custom transport with Go http.Client. type RoundTripper struct { - h host.Host + h host.Host + opts options +} + +// NewTransport returns a new RoundTripper which uses the provided +// libP2P host to perform an http request and obtain the response. +// +// The typical use case for NewTransport is to register the "libp2p" +// protocol with a Transport, as in: +// t := &http.Transport{} +// t.RegisterProtocol("libp2p", p2phttp.NewTransport(host, ProtocolOption(DefaultP2PProtocol))) +// c := &http.Client{Transport: t} +// res, err := c.Get("libp2p://Qmaoi4isbcTbFfohQyn28EiYM5CDWQx9QRCjDh3CTeiY7P/index.html") +// ... +func NewTransport(h host.Host, opts ...Option) *RoundTripper { + defOpts := options{ + Protocol: DefaultP2PProtocol, + } + for _, o := range opts { + o(&defOpts) + } + + return &RoundTripper{h, defOpts} } // we wrap the response body and close the stream @@ -93,7 +130,7 @@ func (rt *RoundTripper) RoundTrip(r *http.Request) (*http.Response, error) { return nil, err } - conn, err := gostream.Dial(rt.h, peer.ID(pid), P2PProtocol) + conn, err := gostream.Dial(rt.h, peer.ID(pid), rt.opts.Protocol) if err != nil { if r.Body != nil { r.Body.Close() @@ -124,17 +161,3 @@ func (rt *RoundTripper) RoundTrip(r *http.Request) (*http.Response, error) { return resp, nil } - -// NewTransport returns a new RoundTripper which uses the provided -// libP2P host to perform an http request and obtain the response. -// -// The typical use case for NewTransport is to register the "libp2p" -// protocol with a Transport, as in: -// t := &http.Transport{} -// t.RegisterProtocol("libp2p", p2phttp.NewTransport(host)) -// c := &http.Client{Transport: t} -// res, err := c.Get("libp2p://Qmaoi4isbcTbFfohQyn28EiYM5CDWQx9QRCjDh3CTeiY7P/index.html") -// ... -func NewTransport(h host.Host) *RoundTripper { - return &RoundTripper{h} -} diff --git a/p2phttp_test.go b/p2phttp_test.go index c6e61ed..2931a7c 100644 --- a/p2phttp_test.go +++ b/p2phttp_test.go @@ -39,7 +39,7 @@ func TestServerClient(t *testing.T) { srvHost.Peerstore().AddAddrs(clientHost.ID(), clientHost.Addrs(), peerstore.PermanentAddrTTL) clientHost.Peerstore().AddAddrs(srvHost.ID(), srvHost.Addrs(), peerstore.PermanentAddrTTL) - listener, err := gostream.Listen(srvHost, P2PProtocol) + listener, err := gostream.Listen(srvHost, "/testiti-test") if err != nil { t.Fatal(err) } @@ -61,7 +61,7 @@ func TestServerClient(t *testing.T) { }() tr := &http.Transport{} - tr.RegisterProtocol("libp2p", NewTransport(clientHost)) + tr.RegisterProtocol("libp2p", NewTransport(clientHost, ProtocolOption("/testiti-test"))) client := &http.Client{Transport: tr} buf := bytes.NewBufferString("Hector")