forked from TrueCloudLab/frostfs-s3-gw
Merge pull request #23 from nspcc-dev/api-handlers
API Handlers (DeleteObject handler)
This commit is contained in:
commit
c9ea63f8ab
4 changed files with 54 additions and 28 deletions
|
@ -34,3 +34,15 @@ func (h *handler) DeleteObjectHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteMultipleObjectsHandler :
|
||||||
|
//
|
||||||
|
// CyberDuck doesn't use that method for multiple delete.
|
||||||
|
// Open issue and describe how to test that method.
|
||||||
|
func (h *handler) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
api.WriteErrorResponse(r.Context(), w, api.Error{
|
||||||
|
Code: "XNeoFSUnimplemented",
|
||||||
|
Description: "implement me " + mux.CurrentRoute(r).GetName(),
|
||||||
|
HTTPStatusCode: http.StatusNotImplemented,
|
||||||
|
}, r.URL)
|
||||||
|
}
|
||||||
|
|
|
@ -358,11 +358,3 @@ func (h *handler) PostPolicyBucketHandler(w http.ResponseWriter, r *http.Request
|
||||||
HTTPStatusCode: http.StatusNotImplemented,
|
HTTPStatusCode: http.StatusNotImplemented,
|
||||||
}, r.URL)
|
}, r.URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *handler) DeleteMultipleObjectsHandler(w http.ResponseWriter, r *http.Request) {
|
|
||||||
api.WriteErrorResponse(r.Context(), w, api.Error{
|
|
||||||
Code: "XNeoFSUnimplemented",
|
|
||||||
Description: "implement me " + mux.CurrentRoute(r).GetName(),
|
|
||||||
HTTPStatusCode: http.StatusNotImplemented,
|
|
||||||
}, r.URL)
|
|
||||||
}
|
|
||||||
|
|
|
@ -371,19 +371,25 @@ func (n *layer) CopyObject(ctx context.Context, p *CopyObjectParams) (*ObjectInf
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteObject from the storage.
|
// DeleteObject removes all objects with passed nice name.
|
||||||
func (n *layer) DeleteObject(ctx context.Context, bucket, object string) error {
|
func (n *layer) DeleteObject(ctx context.Context, bucket, object string) error {
|
||||||
cid, err := refs.CIDFromString(bucket)
|
cid, err := refs.CIDFromString(bucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
oid, err := n.objectFindID(ctx, cid, object, false)
|
ids, err := n.objectFindIDs(ctx, cid, object)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return errors.Wrap(err, "could not find object")
|
||||||
}
|
}
|
||||||
|
|
||||||
return n.objectDelete(ctx, delParams{addr: refs.Address{CID: cid, ObjectID: oid}})
|
for _, id := range ids {
|
||||||
|
if err = n.objectDelete(ctx, delParams{addr: refs.Address{CID: cid, ObjectID: id}}); err != nil {
|
||||||
|
return errors.Wrapf(err, "could not remove object: %s => %s", object, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteObjects from the storage.
|
// DeleteObjects from the storage.
|
||||||
|
|
|
@ -120,13 +120,10 @@ func (n *layer) objectSearchContainer(ctx context.Context, cid refs.CID) ([]refs
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// objectFindID returns object id (uuid) based on it's nice name in s3. If
|
// objectFindIDs returns object id's (uuid) based on they nice name in s3. If
|
||||||
// nice name is uuid compatible, then function returns it.
|
// nice name is uuid compatible, then function returns it.
|
||||||
func (n *layer) objectFindID(ctx context.Context, cid refs.CID, name string, put bool) (refs.ObjectID, error) {
|
func (n *layer) objectFindIDs(ctx context.Context, cid refs.CID, name string) ([]refs.ObjectID, error) {
|
||||||
var (
|
var q query.Query
|
||||||
id refs.ObjectID
|
|
||||||
q query.Query
|
|
||||||
)
|
|
||||||
|
|
||||||
q.Filters = append(q.Filters, query.Filter{
|
q.Filters = append(q.Filters, query.Filter{
|
||||||
Type: query.Filter_Exact,
|
Type: query.Filter_Exact,
|
||||||
|
@ -140,12 +137,12 @@ func (n *layer) objectFindID(ctx context.Context, cid refs.CID, name string, put
|
||||||
|
|
||||||
queryBinary, err := q.Marshal()
|
queryBinary, err := q.Marshal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return id, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := n.cli.GetConnection(ctx)
|
conn, err := n.cli.GetConnection(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return id, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
token, err := n.cli.SessionToken(ctx, &pool.SessionParams{
|
token, err := n.cli.SessionToken(ctx, &pool.SessionParams{
|
||||||
|
@ -154,7 +151,7 @@ func (n *layer) objectFindID(ctx context.Context, cid refs.CID, name string, put
|
||||||
Verb: service.Token_Info_Search,
|
Verb: service.Token_Info_Search,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return id, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
req := new(object.SearchRequest)
|
req := new(object.SearchRequest)
|
||||||
|
@ -167,7 +164,7 @@ func (n *layer) objectFindID(ctx context.Context, cid refs.CID, name string, put
|
||||||
|
|
||||||
err = service.SignRequestData(n.key, req)
|
err = service.SignRequestData(n.key, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return id, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: think about timeout
|
// todo: think about timeout
|
||||||
|
@ -176,7 +173,7 @@ func (n *layer) objectFindID(ctx context.Context, cid refs.CID, name string, put
|
||||||
|
|
||||||
searchClient, err := object.NewServiceClient(conn).Search(ctx, req)
|
searchClient, err := object.NewServiceClient(conn).Search(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return id, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var response []refs.Address
|
var response []refs.Address
|
||||||
|
@ -188,18 +185,33 @@ func (n *layer) objectFindID(ctx context.Context, cid refs.CID, name string, put
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
return id, errors.New("search command received error")
|
return nil, errors.New("search command received error")
|
||||||
}
|
}
|
||||||
|
|
||||||
response = append(response, resp.Addresses...)
|
response = append(response, resp.Addresses...)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ln := len(response); {
|
switch ln := len(response); {
|
||||||
case ln > 1:
|
case ln > 0:
|
||||||
return id, errors.New("several objects with the same name found")
|
result := make([]refs.ObjectID, 0, len(response))
|
||||||
case ln == 1:
|
for i := range response {
|
||||||
return response[0].ObjectID, nil
|
result = append(result, response[i].ObjectID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
default:
|
default:
|
||||||
|
return nil, errors.New("object not found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// objectFindID returns object id (uuid) based on it's nice name in s3. If
|
||||||
|
// nice name is uuid compatible, then function returns it.
|
||||||
|
func (n *layer) objectFindID(ctx context.Context, cid refs.CID, name string, put bool) (refs.ObjectID, error) {
|
||||||
|
var id refs.ObjectID
|
||||||
|
|
||||||
|
if result, err := n.objectFindIDs(ctx, cid, name); err != nil {
|
||||||
|
return id, err
|
||||||
|
} else if ln := len(result); ln == 0 {
|
||||||
// Minio lists all objects with and without nice names. All objects
|
// Minio lists all objects with and without nice names. All objects
|
||||||
// without nice name still have "name" in terms of minio - uuid encoded
|
// without nice name still have "name" in terms of minio - uuid encoded
|
||||||
// into string. There is a tricky case when user upload object
|
// into string. There is a tricky case when user upload object
|
||||||
|
@ -215,7 +227,11 @@ func (n *layer) objectFindID(ctx context.Context, cid refs.CID, name string, put
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return id, errors.New("object not found")
|
return id, errors.New("object not found")
|
||||||
|
} else if ln == 1 {
|
||||||
|
return result[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return id, errors.New("several objects with the same name found")
|
||||||
}
|
}
|
||||||
|
|
||||||
// objectHead returns all object's headers.
|
// objectHead returns all object's headers.
|
||||||
|
|
Loading…
Reference in a new issue