2016-12-16 16:22:37 +00:00
|
|
|
package ipfscluster
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
2016-12-16 18:14:45 +00:00
|
|
|
"net/url"
|
|
|
|
"strconv"
|
2016-12-16 16:22:37 +00:00
|
|
|
"strings"
|
|
|
|
|
|
|
|
cid "github.com/ipfs/go-cid"
|
|
|
|
)
|
|
|
|
|
|
|
|
// This is an ipfs daemon mock which should sustain the functionality used by
|
2016-12-16 18:14:45 +00:00
|
|
|
// ipfscluster.
|
2016-12-16 16:22:37 +00:00
|
|
|
|
|
|
|
type ipfsMock struct {
|
|
|
|
server *httptest.Server
|
2016-12-16 18:14:45 +00:00
|
|
|
addr string
|
|
|
|
port int
|
2016-12-16 16:22:37 +00:00
|
|
|
pinMap *MapState
|
|
|
|
}
|
|
|
|
|
|
|
|
type mockPinResp struct {
|
|
|
|
Pins []string
|
|
|
|
}
|
|
|
|
|
|
|
|
type mockPinType struct {
|
|
|
|
Type string
|
|
|
|
}
|
|
|
|
|
|
|
|
type mockPinLsResp struct {
|
|
|
|
Keys map[string]mockPinType
|
|
|
|
}
|
|
|
|
|
|
|
|
type ipfsErr struct {
|
|
|
|
Code int
|
|
|
|
Message string
|
|
|
|
}
|
|
|
|
|
|
|
|
func newIpfsMock() *ipfsMock {
|
|
|
|
st := NewMapState()
|
|
|
|
m := &ipfsMock{
|
|
|
|
pinMap: st,
|
|
|
|
}
|
|
|
|
ts := httptest.NewServer(http.HandlerFunc(m.handler))
|
|
|
|
m.server = ts
|
2016-12-16 18:14:45 +00:00
|
|
|
|
2016-12-16 21:00:08 +00:00
|
|
|
url, _ := url.Parse(ts.URL)
|
2016-12-16 18:14:45 +00:00
|
|
|
h := strings.Split(url.Host, ":")
|
|
|
|
i, _ := strconv.Atoi(h[1])
|
|
|
|
|
|
|
|
m.port = i
|
|
|
|
m.addr = h[0]
|
2016-12-16 16:22:37 +00:00
|
|
|
return m
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: what if IPFS API changes?
|
|
|
|
func (m *ipfsMock) handler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
p := r.URL.Path
|
|
|
|
endp := strings.TrimPrefix(p, "/api/v0/")
|
|
|
|
var cidStr string
|
|
|
|
switch endp {
|
|
|
|
case "pin/add":
|
|
|
|
query := r.URL.Query()
|
|
|
|
arg, ok := query["arg"]
|
|
|
|
if !ok || len(arg) != 1 {
|
|
|
|
goto ERROR
|
|
|
|
}
|
|
|
|
cidStr = arg[0]
|
|
|
|
if cidStr == errorCid {
|
|
|
|
goto ERROR
|
|
|
|
}
|
|
|
|
c, err := cid.Decode(cidStr)
|
|
|
|
if err != nil {
|
|
|
|
goto ERROR
|
|
|
|
}
|
|
|
|
m.pinMap.AddPin(c)
|
|
|
|
resp := mockPinResp{
|
|
|
|
Pins: []string{cidStr},
|
|
|
|
}
|
|
|
|
j, _ := json.Marshal(resp)
|
|
|
|
w.Write(j)
|
|
|
|
case "pin/rm":
|
|
|
|
query := r.URL.Query()
|
|
|
|
arg, ok := query["arg"]
|
|
|
|
if !ok || len(arg) != 1 {
|
|
|
|
goto ERROR
|
|
|
|
}
|
|
|
|
cidStr = arg[0]
|
|
|
|
c, err := cid.Decode(cidStr)
|
|
|
|
if err != nil {
|
|
|
|
goto ERROR
|
|
|
|
}
|
|
|
|
m.pinMap.RmPin(c)
|
|
|
|
resp := mockPinResp{
|
|
|
|
Pins: []string{cidStr},
|
|
|
|
}
|
|
|
|
j, _ := json.Marshal(resp)
|
|
|
|
w.Write(j)
|
|
|
|
case "pin/ls":
|
|
|
|
query := r.URL.Query()
|
|
|
|
arg, ok := query["arg"]
|
|
|
|
if !ok {
|
|
|
|
rMap := make(map[string]mockPinType)
|
|
|
|
pins := m.pinMap.ListPins()
|
|
|
|
for _, p := range pins {
|
|
|
|
rMap[p.String()] = mockPinType{"recursive"}
|
|
|
|
}
|
|
|
|
j, _ := json.Marshal(mockPinLsResp{rMap})
|
|
|
|
w.Write(j)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if len(arg) != 1 {
|
|
|
|
goto ERROR
|
|
|
|
}
|
|
|
|
cidStr = arg[0]
|
|
|
|
|
|
|
|
c, err := cid.Decode(cidStr)
|
|
|
|
if err != nil {
|
|
|
|
goto ERROR
|
|
|
|
}
|
|
|
|
ok = m.pinMap.HasPin(c)
|
|
|
|
if ok {
|
|
|
|
rMap := make(map[string]mockPinType)
|
|
|
|
rMap[cidStr] = mockPinType{"recursive"}
|
|
|
|
j, _ := json.Marshal(mockPinLsResp{rMap})
|
|
|
|
w.Write(j)
|
|
|
|
} else {
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
resp := ipfsErr{0, fmt.Sprintf("Path '%s' is not pinned", cidStr)}
|
|
|
|
j, _ := json.Marshal(resp)
|
|
|
|
w.Write(j)
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
w.WriteHeader(http.StatusNotFound)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
ERROR:
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *ipfsMock) Close() {
|
|
|
|
m.server.Close()
|
|
|
|
}
|