blob: e662b699c8f2ea11b6e212abaeafeee0a0e3d3d0 [file] [log] [blame]
Jon Perritt8c93a302014-09-28 22:35:57 -05001package objects
2
3import (
4 "fmt"
Ash Wilsonaf262872014-10-20 09:32:29 -04005 "net/http"
Jon Perritt8c93a302014-09-28 22:35:57 -05006 "strings"
7
Ash Wilsonaf262872014-10-20 09:32:29 -04008 "github.com/rackspace/gophercloud"
Jon Perritt8c93a302014-09-28 22:35:57 -05009 "github.com/rackspace/gophercloud/pagination"
Jon Perrittea4e3012014-10-09 22:03:19 -050010
11 "github.com/mitchellh/mapstructure"
Jon Perritt8c93a302014-09-28 22:35:57 -050012)
13
14// Object is a structure that holds information related to a storage object.
Jon Perritt8aa40262014-09-29 15:41:32 -050015type Object struct {
Jon Perrittf3171c12014-09-30 17:39:31 -050016 Bytes int `json:"bytes" mapstructure:"bytes"`
17 ContentType string `json:"content_type" mapstructure:"content_type"`
18 Hash string `json:"hash" mapstructure:"hash"`
19 LastModified string `json:"last_modified" mapstructure:"last_modified"`
20 Name string `json:"name" mapstructure:"name"`
Jon Perritt8aa40262014-09-29 15:41:32 -050021}
Jon Perritt8c93a302014-09-28 22:35:57 -050022
Jamie Hannafordc9cdc8f2014-10-06 16:32:56 +020023// ObjectPage is a single page of objects that is returned from a call to the
24// List function.
Jon Perritt8c93a302014-09-28 22:35:57 -050025type ObjectPage struct {
26 pagination.MarkerPageBase
27}
28
29// IsEmpty returns true if a ListResult contains no object names.
30func (r ObjectPage) IsEmpty() (bool, error) {
31 names, err := ExtractNames(r)
32 if err != nil {
33 return true, err
34 }
35 return len(names) == 0, nil
36}
37
38// LastMarker returns the last object name in a ListResult.
39func (r ObjectPage) LastMarker() (string, error) {
40 names, err := ExtractNames(r)
41 if err != nil {
42 return "", err
43 }
44 if len(names) == 0 {
45 return "", nil
46 }
47 return names[len(names)-1], nil
48}
49
Jon Perritt8c93a302014-09-28 22:35:57 -050050// ExtractInfo is a function that takes a page of objects and returns their full information.
51func ExtractInfo(page pagination.Page) ([]Object, error) {
52 untyped := page.(ObjectPage).Body.([]interface{})
53 results := make([]Object, len(untyped))
54 for index, each := range untyped {
Jon Perritt8aa40262014-09-29 15:41:32 -050055 object := each.(map[string]interface{})
Jon Perrittfdac6e52014-09-29 19:43:45 -050056 err := mapstructure.Decode(object, &results[index])
Jon Perritt8aa40262014-09-29 15:41:32 -050057 if err != nil {
58 return results, err
59 }
Jon Perritt8c93a302014-09-28 22:35:57 -050060 }
61 return results, nil
62}
63
64// ExtractNames is a function that takes a page of objects and returns only their names.
65func ExtractNames(page pagination.Page) ([]string, error) {
66 casted := page.(ObjectPage)
Ash Wilson72e4d2c2014-10-20 10:27:30 -040067 ct := casted.Header.Get("Content-Type")
Jon Perritt8c93a302014-09-28 22:35:57 -050068 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 {
Jon Perritt8aa40262014-09-29 15:41:32 -050077 names = append(names, object.Name)
Jon Perritt8c93a302014-09-28 22:35:57 -050078 }
Jon Perrittfdac6e52014-09-29 19:43:45 -050079
Jon Perritt8c93a302014-09-28 22:35:57 -050080 return names, nil
81 case strings.HasPrefix(ct, "text/plain"):
82 names := make([]string, 0, 50)
83
84 body := string(page.(ObjectPage).Body.([]uint8))
85 for _, name := range strings.Split(body, "\n") {
86 if len(name) > 0 {
87 names = append(names, name)
88 }
89 }
90
91 return names, nil
Jon Perrittfdac6e52014-09-29 19:43:45 -050092 case strings.HasPrefix(ct, "text/html"):
93 return []string{}, nil
Jon Perritt8c93a302014-09-28 22:35:57 -050094 default:
95 return nil, fmt.Errorf("Cannot extract names from response with content-type: [%s]", ct)
96 }
97}
98
Jon Perritt5db08922014-09-30 21:32:48 -050099// DownloadResult is a *http.Response that is returned from a call to the Download function.
100type DownloadResult struct {
Ash Wilsonaf262872014-10-20 09:32:29 -0400101 gophercloud.Result
Jon Perritt5db08922014-09-30 21:32:48 -0500102}
103
Jon Perritt8c93a302014-09-28 22:35:57 -0500104// ExtractContent is a function that takes a DownloadResult (of type *http.Response)
105// and returns the object's content.
106func (dr DownloadResult) ExtractContent() ([]byte, error) {
107 if dr.Err != nil {
Ash Wilsonaf262872014-10-20 09:32:29 -0400108 return nil, dr.Err
Jon Perritt8c93a302014-09-28 22:35:57 -0500109 }
Ash Wilsond3dc2542014-10-20 10:10:48 -0400110 return dr.Body.([]byte), nil
Jon Perritt8c93a302014-09-28 22:35:57 -0500111}
112
Jon Perritt5db08922014-09-30 21:32:48 -0500113// GetResult is a *http.Response that is returned from a call to the Get function.
114type GetResult struct {
Ash Wilsonaf262872014-10-20 09:32:29 -0400115 gophercloud.Result
Jon Perritt5db08922014-09-30 21:32:48 -0500116}
117
Jon Perritt8c93a302014-09-28 22:35:57 -0500118// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
119// and returns the custom metadata associated with the object.
120func (gr GetResult) ExtractMetadata() (map[string]string, error) {
121 if gr.Err != nil {
122 return nil, gr.Err
123 }
124 metadata := make(map[string]string)
Ash Wilson72e4d2c2014-10-20 10:27:30 -0400125 for k, v := range gr.Header {
Jon Perritt8c93a302014-09-28 22:35:57 -0500126 if strings.HasPrefix(k, "X-Object-Meta-") {
127 key := strings.TrimPrefix(k, "X-Object-Meta-")
128 metadata[key] = v[0]
129 }
130 }
131 return metadata, nil
132}
Jon Perritt5db08922014-09-30 21:32:48 -0500133
Ash Wilsonaf262872014-10-20 09:32:29 -0400134type headerResult struct {
135 gophercloud.Result
136}
137
138// Extract returns the unmodified HTTP response headers from a Create, Update, or Delete call, as
139// well as any errors that occurred during the call.
140func (result headerResult) Extract() (http.Header, error) {
Ash Wilson72e4d2c2014-10-20 10:27:30 -0400141 return result.Header, result.Err
Ash Wilsonaf262872014-10-20 09:32:29 -0400142}
143
Jamie Hannafordc9cdc8f2014-10-06 16:32:56 +0200144// CreateResult represents the result of a create operation.
Jon Perritt5db08922014-09-30 21:32:48 -0500145type CreateResult struct {
Ash Wilsonaf262872014-10-20 09:32:29 -0400146 headerResult
Jon Perritt5db08922014-09-30 21:32:48 -0500147}
148
Jamie Hannafordc9cdc8f2014-10-06 16:32:56 +0200149// UpdateResult represents the result of an update operation.
Jon Perritt5db08922014-09-30 21:32:48 -0500150type UpdateResult struct {
Ash Wilsonaf262872014-10-20 09:32:29 -0400151 headerResult
Jon Perritt5db08922014-09-30 21:32:48 -0500152}
153
Jamie Hannafordc9cdc8f2014-10-06 16:32:56 +0200154// DeleteResult represents the result of a delete operation.
Jon Perritt5db08922014-09-30 21:32:48 -0500155type DeleteResult struct {
Ash Wilsonaf262872014-10-20 09:32:29 -0400156 headerResult
Jon Perritt5db08922014-09-30 21:32:48 -0500157}
158
Jamie Hannafordc9cdc8f2014-10-06 16:32:56 +0200159// CopyResult represents the result of a copy operation.
Jon Perritt5db08922014-09-30 21:32:48 -0500160type CopyResult struct {
Ash Wilsonaf262872014-10-20 09:32:29 -0400161 headerResult
Jon Perritt5db08922014-09-30 21:32:48 -0500162}