blob: f7db3edff232acae6a2068492b1a1a118d925f74 [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
Jon Perritt8aa40262014-09-29 15:41:32 -05009 "github.com/mitchellh/mapstructure"
Jon Perritt8c93a302014-09-28 22:35:57 -050010 "github.com/rackspace/gophercloud/pagination"
11)
12
13// Object is a structure that holds information related to a storage object.
Jon Perritt8aa40262014-09-29 15:41:32 -050014type Object struct {
Jon Perrittf3171c12014-09-30 17:39:31 -050015 Bytes int `json:"bytes" mapstructure:"bytes"`
16 ContentType string `json:"content_type" mapstructure:"content_type"`
17 Hash string `json:"hash" mapstructure:"hash"`
18 LastModified string `json:"last_modified" mapstructure:"last_modified"`
19 Name string `json:"name" mapstructure:"name"`
Jon Perritt8aa40262014-09-29 15:41:32 -050020}
Jon Perritt8c93a302014-09-28 22:35:57 -050021
Jamie Hannafordc9cdc8f2014-10-06 16:32:56 +020022// ObjectPage is a single page of objects that is returned from a call to the
23// List function.
Jon Perritt8c93a302014-09-28 22:35:57 -050024type ObjectPage struct {
25 pagination.MarkerPageBase
26}
27
28// IsEmpty returns true if a ListResult contains no object names.
29func (r ObjectPage) IsEmpty() (bool, error) {
30 names, err := ExtractNames(r)
31 if err != nil {
32 return true, err
33 }
34 return len(names) == 0, nil
35}
36
37// LastMarker returns the last object name in a ListResult.
38func (r ObjectPage) LastMarker() (string, error) {
39 names, err := ExtractNames(r)
40 if err != nil {
41 return "", err
42 }
43 if len(names) == 0 {
44 return "", nil
45 }
46 return names[len(names)-1], nil
47}
48
Jon Perritt8c93a302014-09-28 22:35:57 -050049// ExtractInfo is a function that takes a page of objects and returns their full information.
50func ExtractInfo(page pagination.Page) ([]Object, error) {
51 untyped := page.(ObjectPage).Body.([]interface{})
52 results := make([]Object, len(untyped))
53 for index, each := range untyped {
Jon Perritt8aa40262014-09-29 15:41:32 -050054 object := each.(map[string]interface{})
Jon Perrittfdac6e52014-09-29 19:43:45 -050055 err := mapstructure.Decode(object, &results[index])
Jon Perritt8aa40262014-09-29 15:41:32 -050056 if err != nil {
57 return results, err
58 }
Jon Perritt8c93a302014-09-28 22:35:57 -050059 }
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")
Jon Perritt8c93a302014-09-28 22:35:57 -050067 switch {
68 case strings.HasPrefix(ct, "application/json"):
69 parsed, err := ExtractInfo(page)
70 if err != nil {
71 return nil, err
72 }
73
74 names := make([]string, 0, len(parsed))
75 for _, object := range parsed {
Jon Perritt8aa40262014-09-29 15:41:32 -050076 names = append(names, object.Name)
Jon Perritt8c93a302014-09-28 22:35:57 -050077 }
Jon Perrittfdac6e52014-09-29 19:43:45 -050078
Jon Perritt8c93a302014-09-28 22:35:57 -050079 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
Jon Perrittfdac6e52014-09-29 19:43:45 -050091 case strings.HasPrefix(ct, "text/html"):
92 return []string{}, nil
Jon Perritt8c93a302014-09-28 22:35:57 -050093 default:
94 return nil, fmt.Errorf("Cannot extract names from response with content-type: [%s]", ct)
95 }
96}
97
Jon Perritt5db08922014-09-30 21:32:48 -050098// DownloadResult is a *http.Response that is returned from a call to the Download function.
99type DownloadResult struct {
100 commonResult
101}
102
Jon Perritt8c93a302014-09-28 22:35:57 -0500103// ExtractContent is a function that takes a DownloadResult (of type *http.Response)
104// and returns the object's content.
105func (dr DownloadResult) ExtractContent() ([]byte, error) {
106 if dr.Err != nil {
107 return nil, nil
108 }
109 var body []byte
110 defer dr.Resp.Body.Close()
111 body, err := ioutil.ReadAll(dr.Resp.Body)
112 if err != nil {
113 return body, fmt.Errorf("Error trying to read DownloadResult body: %v", err)
114 }
115 return body, nil
116}
117
Jon Perritt5db08922014-09-30 21:32:48 -0500118// GetResult is a *http.Response that is returned from a call to the Get function.
119type GetResult struct {
120 commonResult
121}
122
Jon Perritt8c93a302014-09-28 22:35:57 -0500123// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
124// and returns the custom metadata associated with the object.
125func (gr GetResult) ExtractMetadata() (map[string]string, error) {
126 if gr.Err != nil {
127 return nil, gr.Err
128 }
129 metadata := make(map[string]string)
130 for k, v := range gr.Resp.Header {
131 if strings.HasPrefix(k, "X-Object-Meta-") {
132 key := strings.TrimPrefix(k, "X-Object-Meta-")
133 metadata[key] = v[0]
134 }
135 }
136 return metadata, nil
137}
Jon Perritt5db08922014-09-30 21:32:48 -0500138
139type commonResult struct {
140 Resp *http.Response
141 Err error
142}
143
144func (cr commonResult) ExtractHeaders() (http.Header, error) {
145 var headers http.Header
146 if cr.Err != nil {
147 return headers, cr.Err
148 }
149
150 return cr.Resp.Header, nil
151}
152
Jamie Hannafordc9cdc8f2014-10-06 16:32:56 +0200153// CreateResult represents the result of a create operation.
Jon Perritt5db08922014-09-30 21:32:48 -0500154type CreateResult struct {
155 commonResult
156}
157
Jamie Hannafordc9cdc8f2014-10-06 16:32:56 +0200158// UpdateResult represents the result of an update operation.
Jon Perritt5db08922014-09-30 21:32:48 -0500159type UpdateResult struct {
160 commonResult
161}
162
Jamie Hannafordc9cdc8f2014-10-06 16:32:56 +0200163// DeleteResult represents the result of a delete operation.
Jon Perritt5db08922014-09-30 21:32:48 -0500164type DeleteResult struct {
165 commonResult
166}
167
Jamie Hannafordc9cdc8f2014-10-06 16:32:56 +0200168// CopyResult represents the result of a copy operation.
Jon Perritt5db08922014-09-30 21:32:48 -0500169type CopyResult struct {
170 commonResult
171}