github.com/storacha/go-ucanto@v0.7.2/examples/retrieval/client/client.go (about) 1 package main 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "io" 8 "net/url" 9 "os" 10 "strconv" 11 12 "github.com/multiformats/go-multibase" 13 "github.com/multiformats/go-multihash" 14 "github.com/storacha/go-ucanto/client/retrieval" 15 "github.com/storacha/go-ucanto/core/dag/blockstore" 16 "github.com/storacha/go-ucanto/core/delegation" 17 "github.com/storacha/go-ucanto/core/ipld" 18 "github.com/storacha/go-ucanto/core/receipt" 19 "github.com/storacha/go-ucanto/core/result" 20 "github.com/storacha/go-ucanto/examples/retrieval/capabilities/content" 21 "github.com/storacha/go-ucanto/testing/fixtures" 22 ) 23 24 func main() { 25 // first obtain a delegation from service -> agent (Alice) 26 dlg, err := content.Serve.Delegate( 27 fixtures.Service, 28 fixtures.Alice, 29 fixtures.Service.DID().String(), 30 content.ServeCaveats{}, 31 ) 32 if err != nil { 33 panic(fmt.Errorf("delegating %s to %s: %w", content.Serve.Can(), fixtures.Alice.DID(), err)) 34 } 35 36 if len(os.Args) < 2 { 37 fmt.Println("missing hash argument") 38 os.Exit(1) 39 } 40 41 digestStr := os.Args[1] 42 _, digestBytes, err := multibase.Decode(digestStr) 43 if err != nil { 44 panic(fmt.Errorf("decoding multibase string: %w", err)) 45 } 46 47 digest, err := multihash.Cast(digestBytes) 48 if err != nil { 49 panic(fmt.Errorf("decoding digest: %w", err)) 50 } 51 52 url, err := url.Parse("http://localhost:3000/" + digestStr) 53 if err != nil { 54 panic(fmt.Errorf("parsing retrieval URL: %w", err)) 55 } 56 57 conn, err := retrieval.NewConnection(fixtures.Service, url) 58 if err != nil { 59 panic(fmt.Errorf("creating connection: %w", err)) 60 } 61 62 var byteRange []int 63 if len(os.Args) == 4 { 64 start, err := strconv.Atoi(os.Args[2]) 65 if err != nil { 66 panic(fmt.Errorf("parsing byte range start value: %w", err)) 67 } 68 end, err := strconv.Atoi(os.Args[3]) 69 if err != nil { 70 panic(fmt.Errorf("parsing byte range end value: %w", err)) 71 } 72 byteRange = []int{start, end} 73 } 74 75 inv, err := content.Serve.Invoke( 76 fixtures.Alice, 77 fixtures.Service, 78 fixtures.Service.DID().String(), 79 content.ServeCaveats{Digest: digest, Range: byteRange}, 80 delegation.WithProof(delegation.FromDelegation(dlg)), 81 ) 82 if err != nil { 83 panic(fmt.Errorf("creating invocation: %w", err)) 84 } 85 86 xres, hres, err := retrieval.Execute(context.Background(), inv, conn) 87 if err != nil { 88 panic(fmt.Errorf("executing invocation: %w", err)) 89 } 90 91 rcptLink, ok := xres.Get(inv.Link()) 92 if !ok { 93 panic(errors.New("receipt for invocation not found")) 94 } 95 96 bs, err := blockstore.NewBlockReader(blockstore.WithBlocksIterator(xres.Blocks())) 97 if err != nil { 98 panic(fmt.Errorf("creating block reader: %w", err)) 99 } 100 101 rcpt, err := receipt.NewAnyReceipt(rcptLink, bs) 102 if err != nil { 103 panic(fmt.Errorf("creating receipt: %w", err)) 104 } 105 106 o, x := result.Unwrap(rcpt.Out()) 107 if x != nil { 108 panic(fmt.Errorf("invocation failed: %+v", x)) 109 } 110 111 _, err = ipld.Rebind[content.ServeOk](o, content.ServeTypeSystem.TypeByName("ServeOk")) 112 if err != nil { 113 panic(fmt.Errorf("decoding response: %w", err)) 114 } 115 116 _, err = io.Copy(os.Stdout, hres.Body()) 117 if err != nil { 118 panic(fmt.Errorf("printing body to stdout: %w", err)) 119 } 120 fmt.Println() 121 }