2020-07-03 13:52:04 +00:00
|
|
|
package layer
|
|
|
|
|
|
|
|
import (
|
2020-08-03 11:48:33 +00:00
|
|
|
"net/http"
|
|
|
|
"os"
|
2020-07-03 13:52:04 +00:00
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/nspcc-dev/neofs-api-go/object"
|
2020-08-22 02:37:39 +00:00
|
|
|
"github.com/nspcc-dev/neofs-api-go/refs"
|
2020-07-03 13:52:04 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
2020-08-03 11:48:33 +00:00
|
|
|
ObjectInfo struct {
|
|
|
|
Bucket string
|
|
|
|
Name string
|
|
|
|
Size int64
|
|
|
|
ContentType string
|
|
|
|
Created time.Time
|
2020-08-22 02:37:39 +00:00
|
|
|
Owner refs.OwnerID
|
2020-08-03 11:48:33 +00:00
|
|
|
Headers map[string]string
|
2020-07-03 13:52:04 +00:00
|
|
|
}
|
|
|
|
|
2020-08-03 11:48:33 +00:00
|
|
|
// ListObjectsInfo - container for list objects.
|
|
|
|
ListObjectsInfo struct {
|
|
|
|
// Indicates whether the returned list objects response is truncated. A
|
|
|
|
// value of true indicates that the list was truncated. The list can be truncated
|
|
|
|
// if the number of objects exceeds the limit allowed or specified
|
|
|
|
// by max keys.
|
|
|
|
IsTruncated bool
|
|
|
|
|
|
|
|
// When response is truncated (the IsTruncated element value in the response
|
|
|
|
// is true), you can use the key name in this field as marker in the subsequent
|
|
|
|
// request to get next set of objects.
|
|
|
|
//
|
|
|
|
// NOTE: This element is returned only if you have delimiter request parameter
|
|
|
|
// specified.
|
|
|
|
ContinuationToken string
|
|
|
|
NextContinuationToken string
|
|
|
|
|
|
|
|
// List of objects info for this request.
|
|
|
|
Objects []ObjectInfo
|
|
|
|
|
|
|
|
// List of prefixes for this request.
|
|
|
|
Prefixes []string
|
2020-07-03 13:52:04 +00:00
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2020-08-03 11:48:33 +00:00
|
|
|
const pathSeparator = string(os.PathSeparator)
|
2020-07-03 13:52:04 +00:00
|
|
|
|
|
|
|
func userHeaders(h []object.Header) map[string]string {
|
|
|
|
result := make(map[string]string, len(h))
|
|
|
|
|
|
|
|
for i := range h {
|
|
|
|
switch v := h[i].Value.(type) {
|
|
|
|
case *object.Header_UserHeader:
|
|
|
|
result[v.UserHeader.Key] = v.UserHeader.Value
|
|
|
|
default:
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2020-08-03 11:48:33 +00:00
|
|
|
func objectInfoFromMeta(meta *object.Object) *ObjectInfo {
|
2020-07-03 13:52:04 +00:00
|
|
|
aws3name := meta.SystemHeader.ID.String()
|
|
|
|
|
|
|
|
userHeaders := userHeaders(meta.Headers)
|
|
|
|
if name, ok := userHeaders[AWS3NameHeader]; ok {
|
|
|
|
aws3name = name
|
|
|
|
delete(userHeaders, name)
|
|
|
|
}
|
|
|
|
|
2020-08-03 11:48:33 +00:00
|
|
|
mimeType := http.DetectContentType(meta.Payload)
|
|
|
|
|
|
|
|
return &ObjectInfo{
|
2020-07-03 13:52:04 +00:00
|
|
|
Bucket: meta.SystemHeader.CID.String(),
|
|
|
|
Name: aws3name,
|
2020-08-03 11:48:33 +00:00
|
|
|
ContentType: mimeType,
|
|
|
|
Headers: userHeaders,
|
2020-07-03 13:52:04 +00:00
|
|
|
Size: int64(meta.SystemHeader.PayloadLength),
|
2020-08-03 11:48:33 +00:00
|
|
|
Created: time.Unix(meta.SystemHeader.CreatedAt.UnixTime, 0),
|
2020-07-03 13:52:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func parseUserHeaders(h map[string]string) []object.Header {
|
|
|
|
headers := make([]object.Header, 0, len(h))
|
|
|
|
|
|
|
|
for k, v := range h {
|
|
|
|
uh := &object.UserHeader{Key: k, Value: v}
|
|
|
|
headers = append(headers, object.Header{
|
|
|
|
Value: &object.Header_UserHeader{UserHeader: uh},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return headers
|
|
|
|
}
|
|
|
|
|
|
|
|
func nameFromObject(o *object.Object) (string, string) {
|
|
|
|
var (
|
|
|
|
name string
|
|
|
|
uh = userHeaders(o.Headers)
|
|
|
|
)
|
|
|
|
|
|
|
|
if _, ok := uh[AWS3NameHeader]; !ok {
|
|
|
|
name = o.SystemHeader.ID.String()
|
|
|
|
} else {
|
|
|
|
name = uh[AWS3NameHeader]
|
|
|
|
}
|
|
|
|
|
2020-08-03 11:48:33 +00:00
|
|
|
ind := strings.LastIndex(name, pathSeparator)
|
2020-07-03 13:52:04 +00:00
|
|
|
|
|
|
|
return name[ind+1:], name[:ind+1]
|
|
|
|
}
|