@@ -5,23 +5,43 @@ import (
55 "encoding/json"
66 "errors"
77 "fmt"
8+ "io"
89 "os"
910 "time"
1011
1112 "github.com/ipfs/boxo/ipns"
1213 "github.com/ipfs/boxo/routing/http/client"
1314 "github.com/ipfs/boxo/routing/http/types"
15+ "github.com/ipfs/boxo/routing/http/types/iter"
1416 "github.com/ipfs/go-cid"
1517 "github.com/libp2p/go-libp2p/core/peer"
1618)
1719
18- func findProviders (ctx context.Context , key cid.Cid , endpoint string , prettyOutput bool ) error {
20+ type askClient struct {
21+ drc * client.Client
22+ out io.Writer
23+ pretty bool
24+ }
25+
26+ func newAskClient (endpoint string , prettyOutput bool , out io.Writer ) (* askClient , error ) {
1927 drc , err := client .New (endpoint )
2028 if err != nil {
21- return err
29+ return nil , err
2230 }
2331
24- recordsIter , err := drc .FindProviders (ctx , key )
32+ if out == nil {
33+ out = os .Stdout
34+ }
35+
36+ return & askClient {
37+ drc : drc ,
38+ pretty : prettyOutput ,
39+ out : out ,
40+ }, nil
41+ }
42+
43+ func (a * askClient ) findProviders (ctx context.Context , key cid.Cid ) error {
44+ recordsIter , err := a .drc .FindProviders (ctx , key )
2545 if err != nil {
2646 return err
2747 }
@@ -40,24 +60,24 @@ func findProviders(ctx context.Context, key cid.Cid, endpoint string, prettyOutp
4060 return nil
4161 }
4262
43- if prettyOutput {
63+ if a . pretty {
4464 switch res .Val .GetSchema () {
4565 case types .SchemaPeer :
4666 record := res .Val .(* types.PeerRecord )
47- fmt .Fprintln (os . Stdout , record .ID )
48- fmt .Fprintln (os . Stdout , "\t Protocols:" , record .Protocols )
49- fmt .Fprintln (os . Stdout , "\t Addresses:" , record .Addrs )
67+ fmt .Fprintln (a . out , record .ID )
68+ fmt .Fprintln (a . out , "\t Protocols:" , record .Protocols )
69+ fmt .Fprintln (a . out , "\t Addresses:" , record .Addrs )
5070 default :
5171 // This is an unknown schema. Let's just print it raw.
52- err := json .NewEncoder (os . Stdout ).Encode (res .Val )
72+ err := json .NewEncoder (a . out ).Encode (res .Val )
5373 if err != nil {
5474 return err
5575 }
5676 }
5777
58- fmt .Fprintln (os . Stdout )
78+ fmt .Fprintln (a . out )
5979 } else {
60- err := json .NewEncoder (os . Stdout ).Encode (res .Val )
80+ err := json .NewEncoder (a . out ).Encode (res .Val )
6181 if err != nil {
6282 return err
6383 }
@@ -67,13 +87,56 @@ func findProviders(ctx context.Context, key cid.Cid, endpoint string, prettyOutp
6787 return nil
6888}
6989
70- func findPeers (ctx context.Context , pid peer.ID , endpoint string , prettyOutput bool ) error {
71- drc , err := client .New (endpoint )
90+ func (a * askClient ) provide (ctx context.Context , records ... * types.AnnouncementRecord ) error {
91+ for _ , rec := range records {
92+ err := rec .Verify ()
93+ if err != nil {
94+ return err
95+ }
96+ }
97+
98+ recordsIter , err := a .drc .ProvideRecords (ctx , records ... )
7299 if err != nil {
73100 return err
74101 }
102+ defer recordsIter .Close ()
103+ return a .printProvideResult (recordsIter )
104+ }
105+
106+ func (a * askClient ) printProvideResult (recordsIter iter.ResultIter [* types.AnnouncementResponseRecord ]) error {
107+ for recordsIter .Next () {
108+ res := recordsIter .Val ()
75109
76- recordsIter , err := drc .FindPeers (ctx , pid )
110+ // Check for error, but do not complain if we exceeded the timeout. We are
111+ // expecting that to happen: we explicitly defined a timeout.
112+ if res .Err != nil {
113+ if ! errors .Is (res .Err , context .DeadlineExceeded ) {
114+ return res .Err
115+ }
116+
117+ return nil
118+ }
119+
120+ if a .pretty {
121+ if res .Val .Error != "" {
122+ fmt .Fprintf (a .out , "Error: %s" , res .Val .Error )
123+ } else {
124+ fmt .Fprintf (a .out , "TTL: %s" , res .Val .TTL )
125+ }
126+ fmt .Fprintln (a .out )
127+ } else {
128+ err := json .NewEncoder (a .out ).Encode (res .Val )
129+ if err != nil {
130+ return err
131+ }
132+ }
133+ }
134+
135+ return nil
136+ }
137+
138+ func (a * askClient ) findPeers (ctx context.Context , pid peer.ID ) error {
139+ recordsIter , err := a .drc .FindPeers (ctx , pid )
77140 if err != nil {
78141 return err
79142 }
@@ -92,13 +155,13 @@ func findPeers(ctx context.Context, pid peer.ID, endpoint string, prettyOutput b
92155 return nil
93156 }
94157
95- if prettyOutput {
96- fmt .Fprintln (os . Stdout , res .Val .ID )
97- fmt .Fprintln (os . Stdout , "\t Protocols:" , res .Val .Protocols )
98- fmt .Fprintln (os . Stdout , "\t Addresses:" , res .Val .Addrs )
99- fmt .Fprintln (os . Stdout )
158+ if a . pretty {
159+ fmt .Fprintln (a . out , res .Val .ID )
160+ fmt .Fprintln (a . out , "\t Protocols:" , res .Val .Protocols )
161+ fmt .Fprintln (a . out , "\t Addresses:" , res .Val .Addrs )
162+ fmt .Fprintln (a . out )
100163 } else {
101- err := json .NewEncoder (os . Stdout ).Encode (res .Val )
164+ err := json .NewEncoder (a . out ).Encode (res .Val )
102165 if err != nil {
103166 return err
104167 }
@@ -108,18 +171,30 @@ func findPeers(ctx context.Context, pid peer.ID, endpoint string, prettyOutput b
108171 return nil
109172}
110173
111- func getIPNS (ctx context.Context , name ipns.Name , endpoint string , prettyOutput bool ) error {
112- drc , err := client .New (endpoint )
174+ func (a * askClient ) providePeer (ctx context.Context , records ... * types.AnnouncementRecord ) error {
175+ for _ , rec := range records {
176+ err := rec .Verify ()
177+ if err != nil {
178+ return err
179+ }
180+ }
181+
182+ recordsIter , err := a .drc .ProvidePeerRecords (ctx , records ... )
113183 if err != nil {
114184 return err
115185 }
186+ defer recordsIter .Close ()
116187
117- rec , err := drc .GetIPNS (ctx , name )
188+ return a .printProvideResult (recordsIter )
189+ }
190+
191+ func (a * askClient ) getIPNS (ctx context.Context , name ipns.Name ) error {
192+ rec , err := a .drc .GetIPNS (ctx , name )
118193 if err != nil {
119194 return err
120195 }
121196
122- if prettyOutput {
197+ if a . pretty {
123198 v , err := rec .Value ()
124199 if err != nil {
125200 return err
@@ -135,19 +210,19 @@ func getIPNS(ctx context.Context, name ipns.Name, endpoint string, prettyOutput
135210 return err
136211 }
137212
138- fmt .Printf ( "/ipns/%s\n " , name )
213+ fmt .Fprintf ( a . out , "/ipns/%s\n " , name )
139214
140215 // Since [client.Client.GetIPNS] verifies if the retrieved record is valid, we
141216 // do not need to verify it again. However, if you were not using this specific
142217 // client, but using some other tool, you should always validate the IPNS Record
143218 // using the [ipns.Validate] or [ipns.ValidateWithName] functions.
144- fmt .Println ( "\t Signature Validated" )
145- fmt .Println ( "\t Value:" , v .String ())
146- fmt .Println ( "\t Sequence:" , seq )
147- fmt .Println ( "\t ValidityType : EOL/End-of-Life" )
148- fmt .Println ( "\t Validity:" , eol .Format (time .RFC3339 ))
219+ fmt .Fprintln ( a . out , "\t Signature Validated" )
220+ fmt .Fprintln ( a . out , "\t Value:" , v .String ())
221+ fmt .Fprintln ( a . out , "\t Sequence:" , seq )
222+ fmt .Fprintln ( a . out , "\t ValidityType : EOL/End-of-Life" )
223+ fmt .Fprintln ( a . out , "\t Validity:" , eol .Format (time .RFC3339 ))
149224 if ttl , err := rec .TTL (); err == nil {
150- fmt .Println ( "\t TTL:" , ttl .String ())
225+ fmt .Fprintln ( a . out , "\t TTL:" , ttl .String ())
151226 }
152227
153228 return nil
@@ -158,20 +233,15 @@ func getIPNS(ctx context.Context, name ipns.Name, endpoint string, prettyOutput
158233 return err
159234 }
160235
161- _ , err = os . Stdout .Write (raw )
236+ _ , err = a . out .Write (raw )
162237 return err
163238}
164239
165- func putIPNS (ctx context.Context , name ipns.Name , record []byte , endpoint string ) error {
166- drc , err := client .New (endpoint )
167- if err != nil {
168- return err
169- }
170-
240+ func (a * askClient ) putIPNS (ctx context.Context , name ipns.Name , record []byte ) error {
171241 rec , err := ipns .UnmarshalRecord (record )
172242 if err != nil {
173243 return err
174244 }
175245
176- return drc .PutIPNS (ctx , name , rec )
246+ return a . drc .PutIPNS (ctx , name , rec )
177247}
0 commit comments