/
urlstore.go
135 lines (114 loc) · 3.42 KB
/
urlstore.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package commands
import (
"fmt"
"io"
"net/http"
cmdenv "github.com/ipsn/go-ipfs/core/commands/cmdenv"
filestore "github.com/ipsn/go-ipfs/filestore"
pin "github.com/ipsn/go-ipfs/pin"
chunk "github.com/ipsn/go-ipfs/gxlibs/github.com/ipfs/go-ipfs-chunker"
cid "github.com/ipsn/go-ipfs/gxlibs/github.com/ipfs/go-cid"
cmds "github.com/ipsn/go-ipfs/gxlibs/github.com/ipfs/go-ipfs-cmds"
balanced "github.com/ipsn/go-ipfs/gxlibs/github.com/ipfs/go-unixfs/importer/balanced"
ihelper "github.com/ipsn/go-ipfs/gxlibs/github.com/ipfs/go-unixfs/importer/helpers"
trickle "github.com/ipsn/go-ipfs/gxlibs/github.com/ipfs/go-unixfs/importer/trickle"
cmdkit "github.com/ipsn/go-ipfs/gxlibs/github.com/ipfs/go-ipfs-cmdkit"
mh "github.com/ipsn/go-ipfs/gxlibs/github.com/multiformats/go-multihash"
)
var urlStoreCmd = &cmds.Command{
Subcommands: map[string]*cmds.Command{
"add": urlAdd,
},
}
var urlAdd = &cmds.Command{
Helptext: cmdkit.HelpText{
Tagline: "Add URL via urlstore.",
LongDescription: `
Add URLs to ipfs without storing the data locally.
The URL provided must be stable and ideally on a web server under your
control.
The file is added using raw-leaves but otherwise using the default
settings for 'ipfs add'.
This command is considered temporary until a better solution can be
found. It may disappear or the semantics can change at any
time.
`,
},
Options: []cmdkit.Option{
cmdkit.BoolOption(trickleOptionName, "t", "Use trickle-dag format for dag generation."),
cmdkit.BoolOption(pinOptionName, "Pin this object when adding.").WithDefault(true),
},
Arguments: []cmdkit.Argument{
cmdkit.StringArg("url", true, false, "URL to add to IPFS"),
},
Type: &BlockStat{},
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
url := req.Arguments[0]
n, err := cmdenv.GetNode(env)
if err != nil {
return err
}
if !filestore.IsURL(url) {
return fmt.Errorf("unsupported url syntax: %s", url)
}
cfg, err := n.Repo.Config()
if err != nil {
return err
}
if !cfg.Experimental.UrlstoreEnabled {
return filestore.ErrUrlstoreNotEnabled
}
useTrickledag, _ := req.Options[trickleOptionName].(bool)
dopin, _ := req.Options[pinOptionName].(bool)
hreq, err := http.NewRequest("GET", url, nil)
if err != nil {
return err
}
hres, err := http.DefaultClient.Do(hreq)
if err != nil {
return err
}
if hres.StatusCode != http.StatusOK {
return fmt.Errorf("expected code 200, got: %d", hres.StatusCode)
}
if dopin {
// Take the pinlock
defer n.Blockstore.PinLock().Unlock()
}
chk := chunk.NewSizeSplitter(hres.Body, chunk.DefaultBlockSize)
prefix := cid.NewPrefixV1(cid.DagProtobuf, mh.SHA2_256)
dbp := &ihelper.DagBuilderParams{
Dagserv: n.DAG,
RawLeaves: true,
Maxlinks: ihelper.DefaultLinksPerBlock,
NoCopy: true,
CidBuilder: &prefix,
URL: url,
}
layout := balanced.Layout
if useTrickledag {
layout = trickle.Layout
}
root, err := layout(dbp.New(chk))
if err != nil {
return err
}
c := root.Cid()
if dopin {
n.Pinning.PinWithMode(c, pin.Recursive)
if err := n.Pinning.Flush(); err != nil {
return err
}
}
return cmds.EmitOnce(res, &BlockStat{
Key: c.String(),
Size: int(hres.ContentLength),
})
},
Encoders: cmds.EncoderMap{
cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, bs *BlockStat) error {
_, err := fmt.Fprintln(w, bs.Key)
return err
}),
},
}