api: add authenticated transport, and direct connection
This commit was moved from ipfs/go-ipfs-http-client@d04afa02b059d2c6a631f23a6923eb57ecb21015
Alex committed
Apr 9, 2019 at 19:53 UTC
3b02ea46462d1f87a64e3fe23f73ee0f186b40d5
3 files changed
+80
-2
client/httpapi/api.go
+36
@@ -122,6 +122,42 @@ func NewApiWithClient(a ma.Multiaddr, c *gohttp.Client) (*HttpApi, error) {
122
return api, nil
123
}
124
125
+// NewDirectAPIClient is used to instantiate a HttpApi client
126
+// that connects to an endpoint which leverages additional http paths.
127
+//
128
+// If you need to connect to a IPFS HTTP API located at https://foo.bar/baz/api/v0
129
+// you should use NewDirectAPIClient.
130
+func NewDirectAPIClient(url string) (*HttpApi, error) {
131
+ api := &HttpApi{
132
+ url: url,
133
+ httpcli: gohttp.Client{
134
+ Transport: &gohttp.Transport{
135
+ Proxy: gohttp.ProxyFromEnvironment,
136
+ DisableKeepAlives: true,
137
+ },
138
+ },
139
+ applyGlobal: func(*RequestBuilder) {},
140
+ }
141
+
142
+ // We don't support redirects.
143
+ api.httpcli.CheckRedirect = func(_ *gohttp.Request, _ []*gohttp.Request) error {
144
+ return fmt.Errorf("unexpected redirect")
145
+ }
146
+
147
+ return api, nil
148
+}
149
+
150
+// WithAuthorization is used to wrap an instance of HttpApi
151
+// with an authenticated transport, such as JWT
152
+func (api *HttpApi) WithAuthorization(header, value string) *HttpApi {
153
+ return &HttpApi{
154
+ url: api.url,
155
+ httpcli: gohttp.Client{
156
+ Transport: newAuthenticatedTransport(api.httpcli.Transport, header, value),
157
+ },
158
+ }
159
+}
160
+
161
func (api *HttpApi) WithOptions(opts ...caopts.ApiOption) (iface.CoreAPI, error) {
162
options, err := caopts.ApiOptions(opts...)
163
if err != nil {
client/httpapi/api_test.go
+23
-2
@@ -9,11 +9,11 @@ import (
9
"sync"
10
"testing"
11
12
- "github.com/ipfs/interface-go-ipfs-core"
12
+ iface "github.com/ipfs/interface-go-ipfs-core"
13
"github.com/ipfs/interface-go-ipfs-core/tests"
14
local "github.com/ipfs/iptb-plugins/local"
15
"github.com/ipfs/iptb/testbed"
16
- "github.com/ipfs/iptb/testbed/interfaces"
16
+ testbedi "github.com/ipfs/iptb/testbed/interfaces"
17
ma "github.com/multiformats/go-multiaddr"
18
)
19
@@ -211,3 +211,24 @@ func TestHttpApi(t *testing.T) {
211
212
tests.TestApi(newNodeProvider(ctx))(t)
213
}
214
+
215
+func TestDirectAPI(t *testing.T) {
216
+ type args struct {
217
+ url, header, value string
218
+ }
219
+ tests := []struct {
220
+ name string
221
+ args args
222
+ }{
223
+ {"Success", args{"http://127.0.0.1:5001/foo/bar/api/v0", "Authorization", "Bearer token"}},
224
+ }
225
+ for _, tt := range tests {
226
+ t.Run(tt.name, func(t *testing.T) {
227
+ api, err := NewDirectAPIClient(tt.args.url)
228
+ if err != nil {
229
+ t.Fatal(err)
230
+ }
231
+ api = api.WithAuthorization(tt.args.header, tt.args.value)
232
+ })
233
+ }
234
+}
client/httpapi/transport.go
new
+21
@@ -0,0 +1,21 @@
1
+package httpapi
2
+
3
+import "net/http"
4
+
5
+type transport struct {
6
+ header, value string
7
+ httptr http.RoundTripper
8
+}
9
+
10
+func newAuthenticatedTransport(tr http.RoundTripper, header, value string) *transport {
11
+ return &transport{
12
+ header: header,
13
+ value: value,
14
+ httptr: tr,
15
+ }
16
+}
17
+
18
+func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
19
+ req.Header.Set(t.header, t.value)
20
+ return t.httptr.RoundTrip(req)
21
+}