Skip to content

Commit

Permalink
Fix #854: 404 on deleting a pin that isn't part of pinset (#854)
Browse files Browse the repository at this point in the history
With this commit
- If cid in `DELETE /pins/{cid}` isn't part of the pinset, it would
return 404
- If path in `DELETE /pins/{keyType}/{path}` resolves to a cid that
isn't part of the pinset, it would return 404
  • Loading branch information
kishansagathiya authored and hsanjuan committed Jul 29, 2019
1 parent e0c38a2 commit c0b8301
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 14 deletions.
17 changes: 13 additions & 4 deletions api/rest/restapi.go
Expand Up @@ -22,6 +22,7 @@ import (

"github.com/ipfs/ipfs-cluster/adder/adderutils"
types "github.com/ipfs/ipfs-cluster/api"
"github.com/ipfs/ipfs-cluster/state"

cid "github.com/ipfs/go-cid"
logging "github.com/ipfs/go-log"
Expand Down Expand Up @@ -694,7 +695,7 @@ func (api *API) pinHandler(w http.ResponseWriter, r *http.Request) {
pin,
&pinObj,
)
api.sendResponse(w, http.StatusOK, err, pinObj)
api.sendResponse(w, autoStatus, err, pinObj)
logger.Debug("rest api pinHandler done")
}
}
Expand All @@ -712,7 +713,11 @@ func (api *API) unpinHandler(w http.ResponseWriter, r *http.Request) {
pin,
&pinObj,
)
api.sendResponse(w, http.StatusOK, err, pinObj)
if err != nil && err.Error() == state.ErrNotFound.Error() {
api.sendResponse(w, http.StatusNotFound, err, nil)
return
}
api.sendResponse(w, autoStatus, err, pinObj)
logger.Debug("rest api unpinHandler done")
}
}
Expand All @@ -730,7 +735,7 @@ func (api *API) pinPathHandler(w http.ResponseWriter, r *http.Request) {
&pin,
)

api.sendResponse(w, http.StatusOK, err, pin)
api.sendResponse(w, autoStatus, err, pin)
logger.Debug("rest api pinPathHandler done")
}
}
Expand All @@ -747,7 +752,11 @@ func (api *API) unpinPathHandler(w http.ResponseWriter, r *http.Request) {
pinpath,
&pin,
)
api.sendResponse(w, http.StatusOK, err, pin)
if err != nil && err.Error() == state.ErrNotFound.Error() {
api.sendResponse(w, http.StatusNotFound, err, nil)
return
}
api.sendResponse(w, autoStatus, err, pin)
logger.Debug("rest api unpinPathHandler done")
}
}
Expand Down
18 changes: 15 additions & 3 deletions api/rest/restapi_test.go
Expand Up @@ -631,7 +631,14 @@ var pathTestCases = []pathCase{
http.StatusBadRequest,
"",
},
// TODO: Test StatusNotFound and a case with trailing slash with paths
{
"/ipfs/bafyreiay3jpjk74dkckv2r74eyvf3lfnxujefay2rtuluintasq2zlapv4",
testPinOpts,
true,
http.StatusNotFound,
"",
},
// TODO: A case with trailing slash with paths
// test.PathIPNS2, test.PathIPLD2, test.InvalidPath1
}

Expand All @@ -641,7 +648,7 @@ func TestAPIPinEndpointWithPath(t *testing.T) {
defer rest.Shutdown(ctx)

tf := func(t *testing.T, url urlF) {
for _, testCase := range pathTestCases {
for _, testCase := range pathTestCases[:3] {
c, _ := cid.Decode(testCase.expectedCid)
resultantPin := api.PinWithOpts(
c,
Expand Down Expand Up @@ -689,9 +696,14 @@ func TestAPIUnpinEndpoint(t *testing.T) {
t.Error("expected different error: ", errResp.Message)
}

makeDelete(t, rest, url(rest)+"/pins/"+test.NotFoundCid.String(), &errResp)
if errResp.Code != http.StatusNotFound {
t.Error("expected different error code: ", errResp.Code)
}

makeDelete(t, rest, url(rest)+"/pins/abcd", &errResp)
if errResp.Code != 400 {
t.Error("should fail with bad Cid")
t.Error("expected different error code: ", errResp.Code)
}
}

Expand Down
18 changes: 12 additions & 6 deletions test/cids.go
Expand Up @@ -17,12 +17,15 @@ var (
// ErrorCid is meant to be used as a Cid which causes errors. i.e. the
// ipfs mock fails when pinning this CID.
ErrorCid, _ = cid.Decode("QmP63DkAFEnDYNjDYBpyNDfttu1fvUw99x1brscPzpqmmc")
PeerID1, _ = peer.IDB58Decode("QmXZrtE5jQwXNqCJMfHUTQkvhQ4ZAnqMnmzFMJfLewuabc")
PeerID2, _ = peer.IDB58Decode("QmUZ13osndQ5uL4tPWHXe3iBgBgq9gfewcBMSCAuMBsDJ6")
PeerID3, _ = peer.IDB58Decode("QmPGDFvBkgWhvzEK9qaTWrWurSwqXNmhnK3hgELPdZZNPa")
PeerID4, _ = peer.IDB58Decode("QmZ8naDy5mEz4GLuQwjWt9MPYqHTBbsm8tQBrNSjiq6zBc")
PeerID5, _ = peer.IDB58Decode("QmZVAo3wd8s5eTTy2kPYs34J9PvfxpKPuYsePPYGjgRRjg")
PeerID6, _ = peer.IDB58Decode("QmR8Vu6kZk7JvAN2rWVWgiduHatgBq2bb15Yyq8RRhYSbx")
// NotFoundCid is meant to be used as a CID that doesn't exist in the
// pinset.
NotFoundCid, _ = cid.Decode("bafyreiay3jpjk74dkckv2r74eyvf3lfnxujefay2rtuluintasq2zlapv4")
PeerID1, _ = peer.IDB58Decode("QmXZrtE5jQwXNqCJMfHUTQkvhQ4ZAnqMnmzFMJfLewuabc")
PeerID2, _ = peer.IDB58Decode("QmUZ13osndQ5uL4tPWHXe3iBgBgq9gfewcBMSCAuMBsDJ6")
PeerID3, _ = peer.IDB58Decode("QmPGDFvBkgWhvzEK9qaTWrWurSwqXNmhnK3hgELPdZZNPa")
PeerID4, _ = peer.IDB58Decode("QmZ8naDy5mEz4GLuQwjWt9MPYqHTBbsm8tQBrNSjiq6zBc")
PeerID5, _ = peer.IDB58Decode("QmZVAo3wd8s5eTTy2kPYs34J9PvfxpKPuYsePPYGjgRRjg")
PeerID6, _ = peer.IDB58Decode("QmR8Vu6kZk7JvAN2rWVWgiduHatgBq2bb15Yyq8RRhYSbx")

PeerName1 = "TestPeer1"
PeerName2 = "TestPeer2"
Expand All @@ -39,6 +42,9 @@ var (
PathIPLD1 = "/ipld/QmaNJ5acV31sx8jq626qTpAWW4DXKw34aGhx53dECLvXbY"
PathIPLD2 = "/ipld/QmaNJ5acV31sx8jq626qTpAWW4DXKw34aGhx53dECLvXbY/"

// NotFoundPath is meant to be used as a path that resolves into a CID that doesn't exist in the
// pinset.
NotFoundPath = "/ipfs/bafyreiay3jpjk74dkckv2r74eyvf3lfnxujefay2rtuluintasq2zlapv4"
InvalidPath1 = "/invalidkeytype/QmaNJ5acV31sx8jq626qTpAWW4DXKw34aGhx53dECLvXbY/"
InvalidPath2 = "/ipfs/invalidhash"
InvalidPath3 = "/ipfs/"
Expand Down
10 changes: 9 additions & 1 deletion test/rpc_api_mock.go
Expand Up @@ -8,6 +8,7 @@ import (
"time"

"github.com/ipfs/ipfs-cluster/api"
"github.com/ipfs/ipfs-cluster/state"

cid "github.com/ipfs/go-cid"
gopath "github.com/ipfs/go-path"
Expand Down Expand Up @@ -73,6 +74,9 @@ func (mock *mockCluster) Unpin(ctx context.Context, in *api.Pin, out *api.Pin) e
if in.Cid.Equals(ErrorCid) {
return ErrBadCid
}
if in.Cid.Equals(NotFoundCid) {
return state.ErrNotFound
}
*out = *in
return nil
}
Expand Down Expand Up @@ -102,7 +106,11 @@ func (mock *mockCluster) PinPath(ctx context.Context, in *api.PinPath, out *api.
}

func (mock *mockCluster) UnpinPath(ctx context.Context, in *api.PinPath, out *api.Pin) error {
// Mock-Unpin behaves exactly pin (doing nothing).
if in.Path == NotFoundPath {
return state.ErrNotFound
}

// Mock-Unpin behaves like pin (doing nothing).
return mock.PinPath(ctx, in, out)
}

Expand Down

0 comments on commit c0b8301

Please sign in to comment.