blob: 8808d03ef6dd5267109426603bc861ddc23ff562 [file] [log] [blame]
Jon Perritt8c93a302014-09-28 22:35:57 -05001package objects
2
3import (
4 "fmt"
5 "io/ioutil"
6 "net/http"
7 "strings"
8
9 "github.com/rackspace/gophercloud/pagination"
10)
11
12// Object is a structure that holds information related to a storage object.
13type Object map[string]interface{}
14
15// ListResult is a single page of objects that is returned from a call to the List function.
16type ObjectPage struct {
17 pagination.MarkerPageBase
18}
19
20// IsEmpty returns true if a ListResult contains no object names.
21func (r ObjectPage) IsEmpty() (bool, error) {
22 names, err := ExtractNames(r)
23 if err != nil {
24 return true, err
25 }
26 return len(names) == 0, nil
27}
28
29// LastMarker returns the last object name in a ListResult.
30func (r ObjectPage) LastMarker() (string, error) {
31 names, err := ExtractNames(r)
32 if err != nil {
33 return "", err
34 }
35 if len(names) == 0 {
36 return "", nil
37 }
38 return names[len(names)-1], nil
39}
40
41// DownloadResult is a *http.Response that is returned from a call to the Download function.
42type DownloadResult struct {
43 Resp *http.Response
44 Err error
45}
46
47// GetResult is a *http.Response that is returned from a call to the Get function.
48type GetResult struct {
49 Resp *http.Response
50 Err error
51}
52
53// ExtractInfo is a function that takes a page of objects and returns their full information.
54func ExtractInfo(page pagination.Page) ([]Object, error) {
55 untyped := page.(ObjectPage).Body.([]interface{})
56 results := make([]Object, len(untyped))
57 for index, each := range untyped {
58 results[index] = Object(each.(map[string]interface{}))
59 }
60 return results, nil
61}
62
63// ExtractNames is a function that takes a page of objects and returns only their names.
64func ExtractNames(page pagination.Page) ([]string, error) {
65 casted := page.(ObjectPage)
66 ct := casted.Header.Get("Content-Type")
67
68 switch {
69 case strings.HasPrefix(ct, "application/json"):
70 parsed, err := ExtractInfo(page)
71 if err != nil {
72 return nil, err
73 }
74
75 names := make([]string, 0, len(parsed))
76 for _, object := range parsed {
77 names = append(names, object["name"].(string))
78 }
79 return names, nil
80 case strings.HasPrefix(ct, "text/plain"):
81 names := make([]string, 0, 50)
82
83 body := string(page.(ObjectPage).Body.([]uint8))
84 for _, name := range strings.Split(body, "\n") {
85 if len(name) > 0 {
86 names = append(names, name)
87 }
88 }
89
90 return names, nil
91 default:
92 return nil, fmt.Errorf("Cannot extract names from response with content-type: [%s]", ct)
93 }
94}
95
96// ExtractContent is a function that takes a DownloadResult (of type *http.Response)
97// and returns the object's content.
98func (dr DownloadResult) ExtractContent() ([]byte, error) {
99 if dr.Err != nil {
100 return nil, nil
101 }
102 var body []byte
103 defer dr.Resp.Body.Close()
104 body, err := ioutil.ReadAll(dr.Resp.Body)
105 if err != nil {
106 return body, fmt.Errorf("Error trying to read DownloadResult body: %v", err)
107 }
108 return body, nil
109}
110
111// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
112// and returns the custom metadata associated with the object.
113func (gr GetResult) ExtractMetadata() (map[string]string, error) {
114 if gr.Err != nil {
115 return nil, gr.Err
116 }
117 metadata := make(map[string]string)
118 for k, v := range gr.Resp.Header {
119 if strings.HasPrefix(k, "X-Object-Meta-") {
120 key := strings.TrimPrefix(k, "X-Object-Meta-")
121 metadata[key] = v[0]
122 }
123 }
124 return metadata, nil
125}