fix: use %-encoded headers in most compatible way
Henrique Dias committed
Aug 15, 2023 at 15:11 UTC
1e5ce936596c3404f7a2890ea1827ae743de5fc0
14 files changed
+233
-49
client/rpc/api.go
+53
-6
@@ -1,18 +1,24 @@
1
package rpc
2
3
import (
4
+ "context"
5
+ "encoding/json"
6
"errors"
7
"fmt"
8
"net/http"
9
"os"
10
"path/filepath"
11
"strings"
12
+ "sync"
13
+ "time"
14
15
+ "github.com/blang/semver/v4"
16
iface "github.com/ipfs/boxo/coreiface"
17
caopts "github.com/ipfs/boxo/coreiface/options"
18
"github.com/ipfs/boxo/ipld/merkledag"
19
"github.com/ipfs/go-cid"
20
legacy "github.com/ipfs/go-ipld-legacy"
21
+ ipfs "github.com/ipfs/kubo"
22
dagpb "github.com/ipld/go-codec-dagpb"
23
_ "github.com/ipld/go-ipld-prime/codec/dagcbor"
24
"github.com/ipld/go-ipld-prime/node/basicnode"
@@ -42,6 +48,8 @@ type HttpApi struct {
48
Headers http.Header
49
applyGlobal func(*requestBuilder)
50
ipldDecoder *legacy.Decoder
51
+ versionMu sync.Mutex
52
+ version *semver.Version
53
}
54
55
// NewLocalApi tries to construct new HttpApi instance communicating with local
@@ -151,6 +159,7 @@ func NewURLApiWithClient(url string, c *http.Client) (*HttpApi, error) {
159
api.httpcli.CheckRedirect = func(_ *http.Request, _ []*http.Request) error {
160
return fmt.Errorf("unexpected redirect")
161
}
162
+
163
return api, nil
164
}
165
@@ -160,14 +169,19 @@ func (api *HttpApi) WithOptions(opts ...caopts.ApiOption) (iface.CoreAPI, error)
169
return nil, err
170
}
171
163
- subApi := *api
164
- subApi.applyGlobal = func(req *requestBuilder) {
165
- if options.Offline {
166
- req.Option("offline", options.Offline)
167
- }
172
+ subApi := &HttpApi{
173
+ url: api.url,
174
+ httpcli: api.httpcli,
175
+ Headers: api.Headers,
176
+ applyGlobal: func(req *requestBuilder) {
177
+ if options.Offline {
178
+ req.Option("offline", options.Offline)
179
+ }
180
+ },
181
+ ipldDecoder: api.ipldDecoder,
182
}
183
170
- return &subApi, nil
184
+ return subApi, nil
185
}
186
187
func (api *HttpApi) Request(command string, args ...string) RequestBuilder {
@@ -228,3 +242,36 @@ func (api *HttpApi) PubSub() iface.PubSubAPI {
242
func (api *HttpApi) Routing() iface.RoutingAPI {
243
return (*RoutingAPI)(api)
244
}
245
+
246
+func (api *HttpApi) loadRemoteVersion() (*semver.Version, error) {
247
+ api.versionMu.Lock()
248
+ defer api.versionMu.Unlock()
249
+
250
+ if api.version == nil {
251
+ ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Second*30))
252
+ defer cancel()
253
+
254
+ resp, err := api.Request("version").Send(ctx)
255
+ if err != nil {
256
+ return nil, err
257
+ }
258
+ if resp.Error != nil {
259
+ return nil, resp.Error
260
+ }
261
+ defer resp.Close()
262
+ var out ipfs.VersionInfo
263
+ dec := json.NewDecoder(resp.Output)
264
+ if err := dec.Decode(&out); err != nil {
265
+ return nil, err
266
+ }
267
+
268
+ remoteVersion, err := semver.New(out.Version)
269
+ if err != nil {
270
+ return nil, err
271
+ }
272
+
273
+ api.version = remoteVersion
274
+ }
275
+
276
+ return api.version, nil
277
+}
client/rpc/requestbuilder.go
+27
-6
@@ -8,6 +8,7 @@ import (
8
"strconv"
9
"strings"
10
11
+ "github.com/blang/semver/v4"
12
"github.com/ipfs/boxo/files"
13
)
14
@@ -23,13 +24,18 @@ type RequestBuilder interface {
24
Exec(ctx context.Context, res interface{}) error
25
}
26
27
+// encodedAbsolutePathVersion is the version from which the absolute path header in
28
+// multipart requests is %-encoded. Before this version, its sent raw.
29
+var encodedAbsolutePathVersion = semver.MustParse("0.23.0-dev")
30
+
31
// requestBuilder is an IPFS commands request builder.
32
type requestBuilder struct {
28
- command string
29
- args []string
30
- opts map[string]string
31
- headers map[string]string
32
- body io.Reader
33
+ command string
34
+ args []string
35
+ opts map[string]string
36
+ headers map[string]string
37
+ body io.Reader
38
+ buildError error
39
40
shell *HttpApi
41
}
@@ -60,7 +66,18 @@ func (r *requestBuilder) Body(body io.Reader) RequestBuilder {
66
func (r *requestBuilder) FileBody(body io.Reader) RequestBuilder {
67
pr, _ := files.NewReaderPathFile("/dev/stdin", io.NopCloser(body), nil)
68
d := files.NewMapDirectory(map[string]files.Node{"": pr})
63
- r.body = files.NewMultiFileReader(d, false)
69
+
70
+ version, err := r.shell.loadRemoteVersion()
71
+ if err != nil {
72
+ // Unfortunately, we cannot return an error here. Changing this API is also
73
+ // not the best since we would otherwise have an inconsistent RequestBuilder.
74
+ // We save the error and return it when calling [requestBuilder.Send].
75
+ r.buildError = err
76
+ return r
77
+ }
78
+
79
+ useEncodedAbsPaths := version.LT(encodedAbsolutePathVersion)
80
+ r.body = files.NewMultiFileReader(d, false, useEncodedAbsPaths)
81
82
return r
83
}
@@ -97,6 +114,10 @@ func (r *requestBuilder) Header(name, value string) RequestBuilder {
114
115
// Send sends the request and return the response.
116
func (r *requestBuilder) Send(ctx context.Context) (*Response, error) {
117
+ if r.buildError != nil {
118
+ return nil, r.buildError
119
+ }
120
+
121
r.shell.applyGlobal(r)
122
123
req := NewRequest(ctx, r.shell.url, r.command, r.args...)
client/rpc/unixfs.go
+7
-1
@@ -62,7 +62,13 @@ func (api *UnixfsAPI) Add(ctx context.Context, f files.Node, opts ...caopts.Unix
62
}
63
64
d := files.NewMapDirectory(map[string]files.Node{"": f}) // unwrapped on the other side
65
- req.Body(files.NewMultiFileReader(d, false))
65
+
66
+ version, err := api.core().loadRemoteVersion()
67
+ if err != nil {
68
+ return nil, err
69
+ }
70
+ useEncodedAbsPaths := version.LT(encodedAbsolutePathVersion)
71
+ req.Body(files.NewMultiFileReader(d, false, useEncodedAbsPaths))
72
73
var out addEvent
74
resp, err := req.Send(ctx)
cmd/ipfs/main.go
+57
-2
@@ -2,9 +2,12 @@
2
package main
3
4
import (
5
+ "bytes"
6
"context"
7
+ "encoding/json"
8
"errors"
9
"fmt"
10
+ "io"
11
"net"
12
"net/http"
13
"os"
@@ -12,12 +15,14 @@ import (
15
"strings"
16
"time"
17
18
+ "github.com/blang/semver/v4"
19
"github.com/google/uuid"
20
u "github.com/ipfs/boxo/util"
21
cmds "github.com/ipfs/go-ipfs-cmds"
22
"github.com/ipfs/go-ipfs-cmds/cli"
23
cmdhttp "github.com/ipfs/go-ipfs-cmds/http"
24
logging "github.com/ipfs/go-log"
25
+ ipfs "github.com/ipfs/kubo"
26
"github.com/ipfs/kubo/cmd/ipfs/util"
27
oldcmds "github.com/ipfs/kubo/commands"
28
"github.com/ipfs/kubo/core"
@@ -224,6 +229,10 @@ func apiAddrOption(req *cmds.Request) (ma.Multiaddr, error) {
229
return ma.NewMultiaddr(apiAddrStr)
230
}
231
232
+// encodedAbsolutePathVersion is the version from which the absolute path header in
233
+// multipart requests is %-encoded. Before this version, its sent raw.
234
+var encodedAbsolutePathVersion = semver.MustParse("0.23.0-dev")
235
+
236
func makeExecutor(req *cmds.Request, env interface{}) (cmds.Executor, error) {
237
exe := tracingWrappedExecutor{cmds.NewExecutor(req.Root)}
238
cctx := env.(*oldcmds.Context)
@@ -315,9 +324,18 @@ func makeExecutor(req *cmds.Request, env interface{}) (cmds.Executor, error) {
324
default:
325
return nil, fmt.Errorf("unsupported API address: %s", apiAddr)
326
}
318
- opts = append(opts, cmdhttp.ClientWithHTTPClient(&http.Client{
327
+
328
+ httpClient := &http.Client{
329
Transport: otelhttp.NewTransport(tpt),
320
- }))
330
+ }
331
+ opts = append(opts, cmdhttp.ClientWithHTTPClient(httpClient))
332
+
333
+ // Fetch remove version, as some feature compatibility might change depending on it.
334
+ remoteVersion, err := getRemoteVersion(tracingWrappedExecutor{cmdhttp.NewClient(host, opts...)})
335
+ if err != nil {
336
+ return nil, err
337
+ }
338
+ opts = append(opts, cmdhttp.ClientWithRawAbsPath(remoteVersion.LT(encodedAbsolutePathVersion)))
339
340
return tracingWrappedExecutor{cmdhttp.NewClient(host, opts...)}, nil
341
}
@@ -417,3 +435,40 @@ func resolveAddr(ctx context.Context, addr ma.Multiaddr) (ma.Multiaddr, error) {
435
436
return addrs[0], nil
437
}
438
+
439
+type nopWriter struct {
440
+ io.Writer
441
+}
442
+
443
+func (nw nopWriter) Close() error {
444
+ return nil
445
+}
446
+
447
+func getRemoteVersion(exe cmds.Executor) (*semver.Version, error) {
448
+ ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Second*30))
449
+ defer cancel()
450
+
451
+ req, err := cmds.NewRequest(ctx, []string{"version"}, nil, nil, nil, Root)
452
+ if err != nil {
453
+ return nil, err
454
+ }
455
+
456
+ var buf bytes.Buffer
457
+ re, err := cmds.NewWriterResponseEmitter(nopWriter{&buf}, req)
458
+ if err != nil {
459
+ return nil, err
460
+ }
461
+
462
+ err = exe.Execute(req, re, nil)
463
+ if err != nil {
464
+ return nil, err
465
+ }
466
+
467
+ var out ipfs.VersionInfo
468
+ dec := json.NewDecoder(&buf)
469
+ if err := dec.Decode(&out); err != nil {
470
+ return nil, err
471
+ }
472
+
473
+ return semver.New(out.Version)
474
+}
docs/changelogs/v0.23.md
+16
@@ -8,6 +8,7 @@
8
- [🔦 Highlights](#-highlights)
9
- [Mplex deprecation](#mplex-deprecation)
10
- [Gateway: meaningful CAR responses on Not Found errors](#gateway-meaningful-car-responses-on-not-found-errors)
11
+ - [Binary characters in file names: no longer works with old clients and new Kubo servers](#binary-characters-in-file-names-no-longer-works-with-old-clients-and-new-kubo-servers)
12
- [📝 Changelog](#-changelog)
13
- [👨👩👧👦 Contributors](#-contributors)
14
@@ -43,6 +44,21 @@ the path does not exist, a CAR will be sent with a root of `bafkqaaa` (empty CID
44
This CAR will contain all blocks necessary to validate that the path does not
45
exist without having to trust the gateway.
46
47
+#### Binary characters in file names: no longer works with old clients and new Kubo servers
48
+
49
+In this version, we updated Kubo to support Go 1.20+. In Go 1.20, a regression
50
+regarding multipart headers was [introduced](https://github.com/golang/go/issues/60674).
51
+This only affects `ipfs add` when a file name has binary characters in its name.
52
+As a consequence, we had to update the encoding of the file name headers. This is
53
+the compatibility table:
54
+
55
+| | New Client | Old Client |
56
+|------------|------------|-------------|
57
+| New Server | ✅ | 🟡* |
58
+| Old Server | ✅ | ✅ |
59
+
60
+*Old clients can only send Unicode file paths to the server.
61
+
62
### 📝 Changelog
63
64
### 👨👩👧👦 Contributors
docs/examples/kubo-as-a-library/go.mod
+2
-2
@@ -7,7 +7,7 @@ go 1.20
7
replace github.com/ipfs/kubo => ./../../..
8
9
require (
10
- github.com/ipfs/boxo v0.11.1-0.20230818062747-654231b2bda3
10
+ github.com/ipfs/boxo v0.12.0
11
github.com/ipfs/kubo v0.0.0-00010101000000-000000000000
12
github.com/libp2p/go-libp2p v0.29.2
13
github.com/multiformats/go-multiaddr v0.10.1
@@ -91,7 +91,7 @@ require (
91
github.com/ipfs/go-unixfsnode v1.7.1 // indirect
92
github.com/ipld/go-car/v2 v2.10.2-0.20230622090957-499d0c909d33 // indirect
93
github.com/ipld/go-codec-dagpb v1.6.0 // indirect
94
- github.com/ipld/go-ipld-prime v0.20.0 // indirect
94
+ github.com/ipld/go-ipld-prime v0.21.0 // indirect
95
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
96
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
97
github.com/jbenet/goprocess v0.1.4 // indirect
docs/examples/kubo-as-a-library/go.sum
+6
-6
@@ -159,7 +159,7 @@ github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJn
159
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
160
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
161
github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og=
162
-github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
162
+github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
163
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
164
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
165
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
@@ -301,8 +301,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
301
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
302
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
303
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
304
-github.com/ipfs/boxo v0.11.1-0.20230818062747-654231b2bda3 h1:oiMqmivloEHtlCkS+8rCq1Pkz/rf6m3sC45lL4cnwBA=
305
-github.com/ipfs/boxo v0.11.1-0.20230818062747-654231b2bda3/go.mod h1:8IfDmp+FzFGcF4zjAgHMVPpwYw4AjN9ePEzDfkaYJ1w=
304
+github.com/ipfs/boxo v0.12.0 h1:AXHg/1ONZdRQHQLgG5JHsSC3XoE4DjCAMgK+asZvUcQ=
305
+github.com/ipfs/boxo v0.12.0/go.mod h1:xAnfiU6PtxWCnRqu7dcXQ10bB5/kvI1kXRotuGqGBhg=
306
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
307
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
308
github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY=
@@ -398,8 +398,8 @@ github.com/ipld/go-codec-dagpb v1.6.0 h1:9nYazfyu9B1p3NAgfVdpRco3Fs2nFC72DqVsMj6
398
github.com/ipld/go-codec-dagpb v1.6.0/go.mod h1:ANzFhfP2uMJxRBr8CE+WQWs5UsNa0pYtmKZ+agnUw9s=
399
github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8=
400
github.com/ipld/go-ipld-prime v0.14.1/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0=
401
-github.com/ipld/go-ipld-prime v0.20.0 h1:Ud3VwE9ClxpO2LkCYP7vWPc0Fo+dYdYzgxUJZ3uRG4g=
402
-github.com/ipld/go-ipld-prime v0.20.0/go.mod h1:PzqZ/ZR981eKbgdr3y2DJYeD/8bgMawdGVlJDE8kK+M=
401
+github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E=
402
+github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ=
403
github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20230102063945-1a409dc236dd h1:gMlw/MhNr2Wtp5RwGdsW23cs+yCuj9k2ON7i9MiJlRo=
404
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
405
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
@@ -737,7 +737,7 @@ github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMI
737
github.com/wangjia184/sortedset v0.0.0-20160527075905-f5d03557ba30/go.mod h1:YkocrP2K2tcw938x9gCOmT5G5eCD6jsTz0SZuyAqwIE=
738
github.com/warpfork/go-testmark v0.3.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0=
739
github.com/warpfork/go-testmark v0.9.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0=
740
-github.com/warpfork/go-testmark v0.11.0 h1:J6LnV8KpceDvo7spaNU4+DauH2n1x+6RaO2rJrmpQ9U=
740
+github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s=
741
github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
742
github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
743
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
go.mod
+4
-5
@@ -15,7 +15,7 @@ require (
15
github.com/fsnotify/fsnotify v1.6.0
16
github.com/google/uuid v1.3.0
17
github.com/hashicorp/go-multierror v1.1.1
18
- github.com/ipfs/boxo v0.11.1-0.20230818062747-654231b2bda3
18
+ github.com/ipfs/boxo v0.12.0
19
github.com/ipfs/go-block-format v0.1.2
20
github.com/ipfs/go-cid v0.4.1
21
github.com/ipfs/go-cidutil v0.1.0
@@ -27,7 +27,7 @@ require (
27
github.com/ipfs/go-ds-measure v0.2.0
28
github.com/ipfs/go-fs-lock v0.0.7
29
github.com/ipfs/go-graphsync v0.14.4
30
- github.com/ipfs/go-ipfs-cmds v0.9.0
30
+ github.com/ipfs/go-ipfs-cmds v0.10.0
31
github.com/ipfs/go-ipld-format v0.5.0
32
github.com/ipfs/go-ipld-git v0.1.1
33
github.com/ipfs/go-ipld-legacy v0.2.1
@@ -39,7 +39,7 @@ require (
39
github.com/ipld/go-car v0.5.0
40
github.com/ipld/go-car/v2 v2.10.2-0.20230622090957-499d0c909d33
41
github.com/ipld/go-codec-dagpb v1.6.0
42
- github.com/ipld/go-ipld-prime v0.20.0
42
+ github.com/ipld/go-ipld-prime v0.21.0
43
github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c
44
github.com/jbenet/go-temp-err-catcher v0.1.0
45
github.com/jbenet/goprocess v0.1.4
@@ -92,7 +92,6 @@ require (
92
require (
93
github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 // indirect
94
github.com/Jorropo/jsync v1.0.1 // indirect
95
- github.com/Kubuxu/go-os-helper v0.0.1 // indirect
95
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
96
github.com/alexbrainman/goissue34681 v0.0.0-20191006012335-3fc7a47baff5 // indirect
97
github.com/beorn7/perks v1.0.1 // indirect
@@ -166,7 +165,7 @@ require (
165
github.com/libp2p/go-yamux/v4 v4.0.1 // indirect
166
github.com/libp2p/zeroconf/v2 v2.2.0 // indirect
167
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
169
- github.com/mattn/go-colorable v0.1.4 // indirect
168
+ github.com/mattn/go-colorable v0.1.6 // indirect
169
github.com/mattn/go-isatty v0.0.19 // indirect
170
github.com/mattn/go-runewidth v0.0.4 // indirect
171
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
go.sum
+11
-11
@@ -49,8 +49,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
49
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
50
github.com/Jorropo/jsync v1.0.1 h1:6HgRolFZnsdfzRUj+ImB9og1JYOxQoReSywkHOGSaUU=
51
github.com/Jorropo/jsync v1.0.1/go.mod h1:jCOZj3vrBCri3bSU3ErUYvevKlnbssrXeCivybS5ABQ=
52
-github.com/Kubuxu/go-os-helper v0.0.1 h1:EJiD2VUQyh5A9hWJLmc6iWg6yIcJ7jpBcwC8GMGXfDk=
53
-github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y=
52
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
53
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
54
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
@@ -179,7 +177,7 @@ github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJn
177
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
178
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
179
github.com/frankban/quicktest v1.14.0/go.mod h1:NeW+ay9A/U67EYXNFA1nPE8e/tnQv/09mUdL/ijj8og=
182
-github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
180
+github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
181
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
182
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
183
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
@@ -337,8 +335,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
335
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
336
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
337
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
340
-github.com/ipfs/boxo v0.11.1-0.20230818062747-654231b2bda3 h1:oiMqmivloEHtlCkS+8rCq1Pkz/rf6m3sC45lL4cnwBA=
341
-github.com/ipfs/boxo v0.11.1-0.20230818062747-654231b2bda3/go.mod h1:8IfDmp+FzFGcF4zjAgHMVPpwYw4AjN9ePEzDfkaYJ1w=
338
+github.com/ipfs/boxo v0.12.0 h1:AXHg/1ONZdRQHQLgG5JHsSC3XoE4DjCAMgK+asZvUcQ=
339
+github.com/ipfs/boxo v0.12.0/go.mod h1:xAnfiU6PtxWCnRqu7dcXQ10bB5/kvI1kXRotuGqGBhg=
340
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
341
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
342
github.com/ipfs/go-bitswap v0.11.0 h1:j1WVvhDX1yhG32NTC9xfxnqycqYIlhzEzLXG/cU1HyQ=
@@ -383,8 +381,8 @@ github.com/ipfs/go-ipfs-blockstore v1.3.0 h1:m2EXaWgwTzAfsmt5UdJ7Is6l4gJcaM/A12X
381
github.com/ipfs/go-ipfs-blockstore v1.3.0/go.mod h1:KgtZyc9fq+P2xJUiCAzbRdhhqJHvsw8u2Dlqy2MyRTE=
382
github.com/ipfs/go-ipfs-blocksutil v0.0.1 h1:Eh/H4pc1hsvhzsQoMEP3Bke/aW5P5rVM1IWFJMcGIPQ=
383
github.com/ipfs/go-ipfs-chunker v0.0.5 h1:ojCf7HV/m+uS2vhUGWcogIIxiO5ubl5O57Q7NapWLY8=
386
-github.com/ipfs/go-ipfs-cmds v0.9.0 h1:K0VcXg1l1k6aY6sHnoxYcyimyJQbcV1ueXuWgThmK9Q=
387
-github.com/ipfs/go-ipfs-cmds v0.9.0/go.mod h1:SBFHK8WNwC416QWH9Vz1Ql42SSMAOqKpaHUMBu3jpLo=
384
+github.com/ipfs/go-ipfs-cmds v0.10.0 h1:ZB4+RgYaH4UARfJY0uLKl5UXgApqnRjKbuCiJVcErYk=
385
+github.com/ipfs/go-ipfs-cmds v0.10.0/go.mod h1:sX5d7jkCft9XLPnkgEfXY0z2UBOB5g6fh/obBS0enJE=
386
github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=
387
github.com/ipfs/go-ipfs-delay v0.0.1 h1:r/UXYyRcddO6thwOnhiznIAiSvxMECGgtv35Xs1IeRQ=
388
github.com/ipfs/go-ipfs-delay v0.0.1/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=
@@ -446,8 +444,8 @@ github.com/ipld/go-codec-dagpb v1.6.0 h1:9nYazfyu9B1p3NAgfVdpRco3Fs2nFC72DqVsMj6
444
github.com/ipld/go-codec-dagpb v1.6.0/go.mod h1:ANzFhfP2uMJxRBr8CE+WQWs5UsNa0pYtmKZ+agnUw9s=
445
github.com/ipld/go-ipld-prime v0.11.0/go.mod h1:+WIAkokurHmZ/KwzDOMUuoeJgaRQktHtEaLglS3ZeV8=
446
github.com/ipld/go-ipld-prime v0.14.1/go.mod h1:QcE4Y9n/ZZr8Ijg5bGPT0GqYWgZ1704nH0RDcQtgTP0=
449
-github.com/ipld/go-ipld-prime v0.20.0 h1:Ud3VwE9ClxpO2LkCYP7vWPc0Fo+dYdYzgxUJZ3uRG4g=
450
-github.com/ipld/go-ipld-prime v0.20.0/go.mod h1:PzqZ/ZR981eKbgdr3y2DJYeD/8bgMawdGVlJDE8kK+M=
447
+github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E=
448
+github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ=
449
github.com/ipld/go-ipld-prime/storage/bsadapter v0.0.0-20230102063945-1a409dc236dd h1:gMlw/MhNr2Wtp5RwGdsW23cs+yCuj9k2ON7i9MiJlRo=
450
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
451
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
@@ -572,12 +570,14 @@ github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8
570
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU=
571
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
572
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
575
-github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
573
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
574
+github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
575
+github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
576
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
577
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
578
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
579
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
580
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
581
github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
582
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
583
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
@@ -859,7 +859,7 @@ github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMI
859
github.com/wangjia184/sortedset v0.0.0-20160527075905-f5d03557ba30/go.mod h1:YkocrP2K2tcw938x9gCOmT5G5eCD6jsTz0SZuyAqwIE=
860
github.com/warpfork/go-testmark v0.3.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0=
861
github.com/warpfork/go-testmark v0.9.0/go.mod h1:jhEf8FVxd+F17juRubpmut64NEG6I2rgkUhlcqqXwE0=
862
-github.com/warpfork/go-testmark v0.11.0 h1:J6LnV8KpceDvo7spaNU4+DauH2n1x+6RaO2rJrmpQ9U=
862
+github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s=
863
github.com/warpfork/go-wish v0.0.0-20180510122957-5ad1f5abf436/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
864
github.com/warpfork/go-wish v0.0.0-20200122115046-b9ea61034e4a/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
865
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
test/cli/content_routing_http_test.go
+10
@@ -9,12 +9,14 @@ import (
9
"testing"
10
"time"
11
12
+ "github.com/ipfs/boxo/ipns"
13
"github.com/ipfs/boxo/routing/http/server"
14
"github.com/ipfs/boxo/routing/http/types"
15
"github.com/ipfs/boxo/routing/http/types/iter"
16
"github.com/ipfs/go-cid"
17
"github.com/ipfs/kubo/test/cli/harness"
18
"github.com/ipfs/kubo/test/cli/testutils"
19
+ "github.com/libp2p/go-libp2p/core/routing"
20
"github.com/stretchr/testify/assert"
21
)
22
@@ -45,6 +47,14 @@ func (r *fakeHTTPContentRouter) Provide(ctx context.Context, req *server.WritePr
47
return nil, nil
48
}
49
50
+func (r *fakeHTTPContentRouter) FindIPNSRecord(ctx context.Context, name ipns.Name) (*ipns.Record, error) {
51
+ return nil, routing.ErrNotSupported
52
+}
53
+
54
+func (r *fakeHTTPContentRouter) ProvideIPNSRecord(ctx context.Context, name ipns.Name, rec *ipns.Record) error {
55
+ return routing.ErrNotSupported
56
+}
57
+
58
func (r *fakeHTTPContentRouter) numFindProvidersCalls() int {
59
r.m.Lock()
60
defer r.m.Unlock()
test/dependencies/go.mod
+2
-2
@@ -7,7 +7,7 @@ replace github.com/ipfs/kubo => ../../
7
require (
8
github.com/Kubuxu/gocovmerge v0.0.0-20161216165753-7ecaa51963cd
9
github.com/golangci/golangci-lint v1.54.1
10
- github.com/ipfs/boxo v0.11.1-0.20230818062747-654231b2bda3
10
+ github.com/ipfs/boxo v0.12.0
11
github.com/ipfs/go-cid v0.4.1
12
github.com/ipfs/go-cidutil v0.1.0
13
github.com/ipfs/go-datastore v0.6.0
@@ -16,7 +16,7 @@ require (
16
github.com/ipfs/hang-fds v0.1.0
17
github.com/ipfs/iptb v1.4.0
18
github.com/ipfs/iptb-plugins v0.5.0
19
- github.com/ipld/go-ipld-prime v0.20.0
19
+ github.com/ipld/go-ipld-prime v0.21.0
20
github.com/jbenet/go-random v0.0.0-20190219211222-123a90aedc0c
21
github.com/jbenet/go-random-files v0.0.0-20190219210431-31b3f20ebded
22
github.com/libp2p/go-libp2p v0.29.2
test/dependencies/go.sum
+6
-6
@@ -188,7 +188,7 @@ github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
188
github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
189
github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
190
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
191
-github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
191
+github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
192
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
193
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
194
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
@@ -396,8 +396,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2
396
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
397
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
398
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
399
-github.com/ipfs/boxo v0.11.1-0.20230818062747-654231b2bda3 h1:oiMqmivloEHtlCkS+8rCq1Pkz/rf6m3sC45lL4cnwBA=
400
-github.com/ipfs/boxo v0.11.1-0.20230818062747-654231b2bda3/go.mod h1:8IfDmp+FzFGcF4zjAgHMVPpwYw4AjN9ePEzDfkaYJ1w=
399
+github.com/ipfs/boxo v0.12.0 h1:AXHg/1ONZdRQHQLgG5JHsSC3XoE4DjCAMgK+asZvUcQ=
400
+github.com/ipfs/boxo v0.12.0/go.mod h1:xAnfiU6PtxWCnRqu7dcXQ10bB5/kvI1kXRotuGqGBhg=
401
github.com/ipfs/go-bitfield v1.1.0 h1:fh7FIo8bSwaJEh6DdTWbCeZ1eqOaOkKFI74SCnsWbGA=
402
github.com/ipfs/go-bitfield v1.1.0/go.mod h1:paqf1wjq/D2BBmzfTVFlJQ9IlFOZpg422HL0HqsGWHU=
403
github.com/ipfs/go-block-format v0.1.2 h1:GAjkfhVx1f4YTODS6Esrj1wt2HhrtwTnhEr+DyPUaJo=
@@ -462,8 +462,8 @@ github.com/ipld/go-car v0.5.0 h1:kcCEa3CvYMs0iE5BzD5sV7O2EwMiCIp3uF8tA6APQT8=
462
github.com/ipld/go-car/v2 v2.10.2-0.20230622090957-499d0c909d33 h1:0OZwzSYWIuiKEOXd/2vm5cMcEmmGLFn+1h6lHELCm3s=
463
github.com/ipld/go-codec-dagpb v1.6.0 h1:9nYazfyu9B1p3NAgfVdpRco3Fs2nFC72DqVsMj6rOcc=
464
github.com/ipld/go-codec-dagpb v1.6.0/go.mod h1:ANzFhfP2uMJxRBr8CE+WQWs5UsNa0pYtmKZ+agnUw9s=
465
-github.com/ipld/go-ipld-prime v0.20.0 h1:Ud3VwE9ClxpO2LkCYP7vWPc0Fo+dYdYzgxUJZ3uRG4g=
466
-github.com/ipld/go-ipld-prime v0.20.0/go.mod h1:PzqZ/ZR981eKbgdr3y2DJYeD/8bgMawdGVlJDE8kK+M=
465
+github.com/ipld/go-ipld-prime v0.21.0 h1:n4JmcpOlPDIxBcY037SVfpd1G+Sj1nKZah0m6QH9C2E=
466
+github.com/ipld/go-ipld-prime v0.21.0/go.mod h1:3RLqy//ERg/y5oShXXdx5YIp50cFGOanyMctpPjsvxQ=
467
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
468
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
469
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
@@ -885,7 +885,7 @@ github.com/uudashr/gocognit v1.0.7 h1:e9aFXgKgUJrQ5+bs61zBigmj7bFJ/5cC6HmMahVzuD
885
github.com/uudashr/gocognit v1.0.7/go.mod h1:nAIUuVBnYU7pcninia3BHOvQkpQCeO76Uscky5BOwcY=
886
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
887
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
888
-github.com/warpfork/go-testmark v0.11.0 h1:J6LnV8KpceDvo7spaNU4+DauH2n1x+6RaO2rJrmpQ9U=
888
+github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s=
889
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
890
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
891
github.com/whyrusleeping/cbor v0.0.0-20171005072247-63513f603b11 h1:5HZfQkwe0mIfyDmc1Em5GqlNRzcdtlv4HTNmdpt7XH0=
test/sharness/t0235-cli-request.sh
+16
-1
@@ -31,7 +31,22 @@ test_expect_success "can make http request against nc server" '
31
ipfs cat /ipfs/Qmabcdef --api /ip4/127.0.0.1/tcp/5005 &
32
IPFSPID=$!
33
34
- # handle request
34
+ # handle request for /api/v0/version
35
+ while read line; do
36
+ if [[ "$line" == "$(echo -e "\r")" ]]; then
37
+ break
38
+ fi
39
+ echo "$line"
40
+ done <&7 >nc_out &&
41
+
42
+ echo -e "HTTP/1.1 200 OK\r" >&6 &&
43
+ echo -e "Content-Type: application/json\r" >&6 &&
44
+ echo -e "Content-Length: 21\r" >&6 &&
45
+ echo -e "\r" >&6 &&
46
+ echo -e "{\"Version\":\"0.23.0\"}\r" >&6 &&
47
+ echo -e "\r" >&6 &&
48
+
49
+ # handle request for /api/v0/cat
50
while read line; do
51
if [[ "$line" == "$(echo -e "\r")" ]]; then
52
break
test/sharness/t0236-cli-api-dns-resolve.sh
+16
-1
@@ -30,7 +30,22 @@ test_expect_success "can make http request against dns resolved nc server" '
30
ipfs cat /ipfs/Qmabcdef --api /dns4/localhost/tcp/5006 &
31
IPFSPID=$!
32
33
- # handle request
33
+ # handle request for /api/v0/version
34
+ while read line; do
35
+ if [[ "$line" == "$(echo -e "\r")" ]]; then
36
+ break
37
+ fi
38
+ echo "$line"
39
+ done <&7 >nc_out &&
40
+
41
+ echo -e "HTTP/1.1 200 OK\r" >&6 &&
42
+ echo -e "Content-Type: application/json\r" >&6 &&
43
+ echo -e "Content-Length: 21\r" >&6 &&
44
+ echo -e "\r" >&6 &&
45
+ echo -e "{\"Version\":\"0.23.0\"}\r" >&6 &&
46
+ echo -e "\r" >&6 &&
47
+
48
+ # handle request for /api/v0/cat
49
while read line; do
50
if [[ "$line" == "$(echo -e "\r")" ]]; then
51
break