/
ipfs.go
107 lines (91 loc) · 2.19 KB
/
ipfs.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package storage
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"mime/multipart"
"net/http"
"strings"
)
type ipfsStore struct {
host string
encoding AddressEncoding
}
func NewIPFSStore(host string, encoding AddressEncoding) (*ipfsStore, error) {
host = fmt.Sprintf("%s/api/v0", strings.TrimRight(host, "/"))
_, err := http.Get(host)
if err != nil {
return nil, err
}
return &ipfsStore{
host: host,
encoding: encoding,
}, nil
}
func (inv *ipfsStore) Put(address []byte, data []byte) ([]byte, error) {
url := fmt.Sprintf("%s/add", inv.host)
var b bytes.Buffer
w := multipart.NewWriter(&b)
// https://docs.ipfs.io/reference/api/http/
fw, err := w.CreateFormField("arg")
if _, err = fw.Write((data)[:]); err != nil {
return address, nil
}
w.Close()
// pinning is true by default
req, err := http.NewRequest("POST", url, &b)
req.Header.Set("Content-Type", w.FormDataContentType())
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return address, err
}
defer resp.Body.Close()
body := &bytes.Buffer{}
_, err = body.ReadFrom(resp.Body)
if err != nil {
return address, err
}
var m map[string]interface{}
json.Unmarshal(body.Bytes(), &m)
// currently, we `add` the blob and read the return address
return []byte(m["Name"].(string)), nil
}
func (inv *ipfsStore) Get(address []byte) ([]byte, error) {
url := fmt.Sprintf("%s/cat?arg=%s", inv.host, string(address))
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return body, nil
}
func (inv *ipfsStore) Stat(address []byte) (*StatInfo, error) {
url := fmt.Sprintf("%s/cat?arg=%s", inv.host, string(address))
resp, err := http.Get(url)
if err != nil || resp.StatusCode != 200 {
return &StatInfo{
Exists: false,
}, nil
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return &StatInfo{
Exists: true,
Size_: uint64(len(body)),
}, nil
}
func (inv *ipfsStore) Location(address []byte) string {
return string(address)
}
func (inv *ipfsStore) Name() string {
return fmt.Sprintf("ipfsStore[api=%s]", inv.host)
}