blob: 0dcdbe2fbecd5ef497c0ae3401326e69625c5765 [file] [log] [blame]
Jon Perritt8c93a302014-09-28 22:35:57 -05001package objects
2
3import (
jrperritt655245a2016-08-31 15:30:27 -05004 "encoding/json"
Jon Perritt8c93a302014-09-28 22:35:57 -05005 "fmt"
Jamie Hannaford2e784862014-10-27 10:40:27 +01006 "io"
7 "io/ioutil"
jrperritt655245a2016-08-31 15:30:27 -05008 "strconv"
Jon Perritt8c93a302014-09-28 22:35:57 -05009 "strings"
jrperritt98d01622017-01-12 14:24:42 -060010 "time"
Jon Perritt8c93a302014-09-28 22:35:57 -050011
Jon Perritt27249f42016-02-18 10:35:59 -060012 "github.com/gophercloud/gophercloud"
13 "github.com/gophercloud/gophercloud/pagination"
Jon Perritt8c93a302014-09-28 22:35:57 -050014)
15
16// Object is a structure that holds information related to a storage object.
Jon Perritt8aa40262014-09-29 15:41:32 -050017type Object struct {
Jon Perritt9415ca72014-11-03 11:58:48 -060018 // Bytes is the total number of bytes that comprise the object.
Jon Perritt3c166472016-02-25 03:07:41 -060019 Bytes int64 `json:"bytes"`
Jon Perritt9415ca72014-11-03 11:58:48 -060020
21 // ContentType is the content type of the object.
Jon Perritt3c166472016-02-25 03:07:41 -060022 ContentType string `json:"content_type"`
Jon Perritt9415ca72014-11-03 11:58:48 -060023
24 // Hash represents the MD5 checksum value of the object's content.
Jon Perritt3c166472016-02-25 03:07:41 -060025 Hash string `json:"hash"`
Jon Perritt9415ca72014-11-03 11:58:48 -060026
jrperritt98d01622017-01-12 14:24:42 -060027 // LastModified is the time the object was last modified, represented
28 // as a string.
29 LastModified time.Time `json:"-"`
Jon Perritt9415ca72014-11-03 11:58:48 -060030
31 // Name is the unique name for the object.
Jon Perritt3c166472016-02-25 03:07:41 -060032 Name string `json:"name"`
Jon Perritt8aa40262014-09-29 15:41:32 -050033}
Jon Perritt8c93a302014-09-28 22:35:57 -050034
jrperritt98d01622017-01-12 14:24:42 -060035func (r *Object) UnmarshalJSON(b []byte) error {
36 type tmp Object
37 var s *struct {
38 tmp
39 LastModified gophercloud.JSONRFC3339MilliNoZ `json:"last_modified"`
40 }
41
42 err := json.Unmarshal(b, &s)
43 if err != nil {
44 return err
45 }
46
47 *r = Object(s.tmp)
48
49 r.LastModified = time.Time(s.LastModified)
50
51 return nil
52
53}
54
Jamie Hannafordc9cdc8f2014-10-06 16:32:56 +020055// ObjectPage is a single page of objects that is returned from a call to the
56// List function.
Jon Perritt8c93a302014-09-28 22:35:57 -050057type ObjectPage struct {
58 pagination.MarkerPageBase
59}
60
61// IsEmpty returns true if a ListResult contains no object names.
62func (r ObjectPage) IsEmpty() (bool, error) {
63 names, err := ExtractNames(r)
Jon Perritt3c166472016-02-25 03:07:41 -060064 return len(names) == 0, err
Jon Perritt8c93a302014-09-28 22:35:57 -050065}
66
67// LastMarker returns the last object name in a ListResult.
68func (r ObjectPage) LastMarker() (string, error) {
69 names, err := ExtractNames(r)
70 if err != nil {
71 return "", err
72 }
73 if len(names) == 0 {
74 return "", nil
75 }
76 return names[len(names)-1], nil
77}
78
Jon Perritt8c93a302014-09-28 22:35:57 -050079// ExtractInfo is a function that takes a page of objects and returns their full information.
Jon Perritt3c166472016-02-25 03:07:41 -060080func ExtractInfo(r pagination.Page) ([]Object, error) {
81 var s []Object
82 err := (r.(ObjectPage)).ExtractInto(&s)
83 return s, err
Jon Perritt8c93a302014-09-28 22:35:57 -050084}
85
86// ExtractNames is a function that takes a page of objects and returns only their names.
Jon Perritt3c166472016-02-25 03:07:41 -060087func ExtractNames(r pagination.Page) ([]string, error) {
88 casted := r.(ObjectPage)
Ash Wilson72e4d2c2014-10-20 10:27:30 -040089 ct := casted.Header.Get("Content-Type")
Jon Perritt8c93a302014-09-28 22:35:57 -050090 switch {
91 case strings.HasPrefix(ct, "application/json"):
Jon Perritt3c166472016-02-25 03:07:41 -060092 parsed, err := ExtractInfo(r)
Jon Perritt8c93a302014-09-28 22:35:57 -050093 if err != nil {
94 return nil, err
95 }
96
97 names := make([]string, 0, len(parsed))
98 for _, object := range parsed {
Jon Perritt8aa40262014-09-29 15:41:32 -050099 names = append(names, object.Name)
Jon Perritt8c93a302014-09-28 22:35:57 -0500100 }
Jon Perrittfdac6e52014-09-29 19:43:45 -0500101
Jon Perritt8c93a302014-09-28 22:35:57 -0500102 return names, nil
103 case strings.HasPrefix(ct, "text/plain"):
104 names := make([]string, 0, 50)
105
Jon Perritt3c166472016-02-25 03:07:41 -0600106 body := string(r.(ObjectPage).Body.([]uint8))
Jon Perritt8c93a302014-09-28 22:35:57 -0500107 for _, name := range strings.Split(body, "\n") {
108 if len(name) > 0 {
109 names = append(names, name)
110 }
111 }
112
113 return names, nil
Jon Perrittfdac6e52014-09-29 19:43:45 -0500114 case strings.HasPrefix(ct, "text/html"):
115 return []string{}, nil
Jon Perritt8c93a302014-09-28 22:35:57 -0500116 default:
117 return nil, fmt.Errorf("Cannot extract names from response with content-type: [%s]", ct)
118 }
119}
120
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700121// DownloadHeader represents the headers returned in the response from a Download request.
122type DownloadHeader struct {
jrperritt98d01622017-01-12 14:24:42 -0600123 AcceptRanges string `json:"Accept-Ranges"`
124 ContentDisposition string `json:"Content-Disposition"`
125 ContentEncoding string `json:"Content-Encoding"`
126 ContentLength int64 `json:"-"`
127 ContentType string `json:"Content-Type"`
128 Date time.Time `json:"-"`
129 DeleteAt time.Time `json:"-"`
130 ETag string `json:"Etag"`
131 LastModified time.Time `json:"-"`
132 ObjectManifest string `json:"X-Object-Manifest"`
133 StaticLargeObject bool `json:"X-Static-Large-Object"`
134 TransID string `json:"X-Trans-Id"`
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700135}
136
jrperritt98d01622017-01-12 14:24:42 -0600137func (r *DownloadHeader) UnmarshalJSON(b []byte) error {
jrperritt655245a2016-08-31 15:30:27 -0500138 type tmp DownloadHeader
jrperritt98d01622017-01-12 14:24:42 -0600139 var s struct {
jrperritt655245a2016-08-31 15:30:27 -0500140 tmp
jrperritt98d01622017-01-12 14:24:42 -0600141 ContentLength string `json:"Content-Length"`
142 Date gophercloud.JSONRFC1123 `json:"Date"`
143 DeleteAt gophercloud.JSONUnix `json:"X-Delete-At"`
144 LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
jrperritt655245a2016-08-31 15:30:27 -0500145 }
jrperritt98d01622017-01-12 14:24:42 -0600146 err := json.Unmarshal(b, &s)
jrperritt655245a2016-08-31 15:30:27 -0500147 if err != nil {
148 return err
149 }
150
jrperritt98d01622017-01-12 14:24:42 -0600151 *r = DownloadHeader(s.tmp)
jrperritt655245a2016-08-31 15:30:27 -0500152
jrperritt98d01622017-01-12 14:24:42 -0600153 switch s.ContentLength {
jrperritt655245a2016-08-31 15:30:27 -0500154 case "":
jrperritt98d01622017-01-12 14:24:42 -0600155 r.ContentLength = 0
jrperritt655245a2016-08-31 15:30:27 -0500156 default:
jrperritt98d01622017-01-12 14:24:42 -0600157 r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64)
jrperritt655245a2016-08-31 15:30:27 -0500158 if err != nil {
159 return err
160 }
161 }
162
jrperritt98d01622017-01-12 14:24:42 -0600163 r.Date = time.Time(s.Date)
164 r.DeleteAt = time.Time(s.DeleteAt)
165 r.LastModified = time.Time(s.LastModified)
166
jrperritt655245a2016-08-31 15:30:27 -0500167 return nil
168}
169
Jon Perritt5db08922014-09-30 21:32:48 -0500170// DownloadResult is a *http.Response that is returned from a call to the Download function.
171type DownloadResult struct {
Jon Perrittd50f93e2014-10-27 14:19:27 -0500172 gophercloud.HeaderResult
Jamie Hannafordee115552014-10-27 16:11:05 +0100173 Body io.ReadCloser
Jon Perritt5db08922014-09-30 21:32:48 -0500174}
175
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700176// Extract will return a struct of headers returned from a call to Download. To obtain
177// a map of headers, call the ExtractHeader method on the DownloadResult.
Jon Perritt3c166472016-02-25 03:07:41 -0600178func (r DownloadResult) Extract() (*DownloadHeader, error) {
179 var s *DownloadHeader
180 err := r.ExtractInto(&s)
181 return s, err
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700182}
183
Jamie Hannaford2e784862014-10-27 10:40:27 +0100184// ExtractContent is a function that takes a DownloadResult's io.Reader body
185// and reads all available data into a slice of bytes. Please be aware that due
186// the nature of io.Reader is forward-only - meaning that it can only be read
187// once and not rewound. You can recreate a reader from the output of this
188// function by using bytes.NewReader(downloadBytes)
Jon Perritt3c166472016-02-25 03:07:41 -0600189func (r *DownloadResult) ExtractContent() ([]byte, error) {
190 if r.Err != nil {
191 return nil, r.Err
Jon Perritt8c93a302014-09-28 22:35:57 -0500192 }
Jon Perritt3c166472016-02-25 03:07:41 -0600193 defer r.Body.Close()
194 body, err := ioutil.ReadAll(r.Body)
Jamie Hannaford2e784862014-10-27 10:40:27 +0100195 if err != nil {
196 return nil, err
197 }
Jon Perritt3c166472016-02-25 03:07:41 -0600198 r.Body.Close()
Jamie Hannaford2e784862014-10-27 10:40:27 +0100199 return body, nil
Jon Perritt8c93a302014-09-28 22:35:57 -0500200}
201
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700202// GetHeader represents the headers returned in the response from a Get request.
203type GetHeader struct {
jrperritt98d01622017-01-12 14:24:42 -0600204 ContentDisposition string `json:"Content-Disposition"`
205 ContentEncoding string `json:"Content-Encoding"`
206 ContentLength int64 `json:"-"`
207 ContentType string `json:"Content-Type"`
208 Date time.Time `json:"-"`
209 DeleteAt time.Time `json:"-"`
210 ETag string `json:"Etag"`
211 LastModified time.Time `json:"-"`
212 ObjectManifest string `json:"X-Object-Manifest"`
213 StaticLargeObject bool `json:"X-Static-Large-Object"`
214 TransID string `json:"X-Trans-Id"`
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700215}
216
jrperritt98d01622017-01-12 14:24:42 -0600217func (r *GetHeader) UnmarshalJSON(b []byte) error {
jrperritt655245a2016-08-31 15:30:27 -0500218 type tmp GetHeader
jrperritt98d01622017-01-12 14:24:42 -0600219 var s struct {
jrperritt655245a2016-08-31 15:30:27 -0500220 tmp
jrperritt98d01622017-01-12 14:24:42 -0600221 ContentLength string `json:"Content-Length"`
222 Date gophercloud.JSONRFC1123 `json:"Date"`
223 DeleteAt gophercloud.JSONUnix `json:"X-Delete-At"`
224 LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
jrperritt655245a2016-08-31 15:30:27 -0500225 }
jrperritt98d01622017-01-12 14:24:42 -0600226 err := json.Unmarshal(b, &s)
jrperritt655245a2016-08-31 15:30:27 -0500227 if err != nil {
228 return err
229 }
230
jrperritt98d01622017-01-12 14:24:42 -0600231 *r = GetHeader(s.tmp)
jrperritt655245a2016-08-31 15:30:27 -0500232
jrperritt98d01622017-01-12 14:24:42 -0600233 switch s.ContentLength {
jrperritt655245a2016-08-31 15:30:27 -0500234 case "":
jrperritt98d01622017-01-12 14:24:42 -0600235 r.ContentLength = 0
jrperritt655245a2016-08-31 15:30:27 -0500236 default:
jrperritt98d01622017-01-12 14:24:42 -0600237 r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64)
jrperritt655245a2016-08-31 15:30:27 -0500238 if err != nil {
239 return err
240 }
241 }
242
jrperritt98d01622017-01-12 14:24:42 -0600243 r.Date = time.Time(s.Date)
244 r.DeleteAt = time.Time(s.DeleteAt)
245 r.LastModified = time.Time(s.LastModified)
246
jrperritt655245a2016-08-31 15:30:27 -0500247 return nil
248}
249
Jon Perritt5db08922014-09-30 21:32:48 -0500250// GetResult is a *http.Response that is returned from a call to the Get function.
251type GetResult struct {
Jon Perrittd50f93e2014-10-27 14:19:27 -0500252 gophercloud.HeaderResult
Jon Perritt5db08922014-09-30 21:32:48 -0500253}
254
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700255// Extract will return a struct of headers returned from a call to Get. To obtain
256// a map of headers, call the ExtractHeader method on the GetResult.
Jon Perritt3c166472016-02-25 03:07:41 -0600257func (r GetResult) Extract() (*GetHeader, error) {
258 var s *GetHeader
259 err := r.ExtractInto(&s)
260 return s, err
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700261}
262
Jon Perritt8c93a302014-09-28 22:35:57 -0500263// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
264// and returns the custom metadata associated with the object.
Jon Perritt3c166472016-02-25 03:07:41 -0600265func (r GetResult) ExtractMetadata() (map[string]string, error) {
266 if r.Err != nil {
267 return nil, r.Err
Jon Perritt8c93a302014-09-28 22:35:57 -0500268 }
269 metadata := make(map[string]string)
Jon Perritt3c166472016-02-25 03:07:41 -0600270 for k, v := range r.Header {
Jon Perritt8c93a302014-09-28 22:35:57 -0500271 if strings.HasPrefix(k, "X-Object-Meta-") {
272 key := strings.TrimPrefix(k, "X-Object-Meta-")
273 metadata[key] = v[0]
274 }
275 }
276 return metadata, nil
277}
Jon Perritt5db08922014-09-30 21:32:48 -0500278
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700279// CreateHeader represents the headers returned in the response from a Create request.
280type CreateHeader struct {
jrperritt98d01622017-01-12 14:24:42 -0600281 ContentLength int64 `json:"-"`
282 ContentType string `json:"Content-Type"`
283 Date time.Time `json:"-"`
284 ETag string `json:"Etag"`
285 LastModified time.Time `json:"-"`
286 TransID string `json:"X-Trans-Id"`
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700287}
288
jrperritt98d01622017-01-12 14:24:42 -0600289func (r *CreateHeader) UnmarshalJSON(b []byte) error {
jrperritt655245a2016-08-31 15:30:27 -0500290 type tmp CreateHeader
jrperritt98d01622017-01-12 14:24:42 -0600291 var s struct {
jrperritt655245a2016-08-31 15:30:27 -0500292 tmp
jrperritt98d01622017-01-12 14:24:42 -0600293 ContentLength string `json:"Content-Length"`
294 Date gophercloud.JSONRFC1123 `json:"Date"`
295 LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
jrperritt655245a2016-08-31 15:30:27 -0500296 }
jrperritt98d01622017-01-12 14:24:42 -0600297 err := json.Unmarshal(b, &s)
jrperritt655245a2016-08-31 15:30:27 -0500298 if err != nil {
299 return err
300 }
301
jrperritt98d01622017-01-12 14:24:42 -0600302 *r = CreateHeader(s.tmp)
jrperritt655245a2016-08-31 15:30:27 -0500303
jrperritt98d01622017-01-12 14:24:42 -0600304 switch s.ContentLength {
jrperritt655245a2016-08-31 15:30:27 -0500305 case "":
jrperritt98d01622017-01-12 14:24:42 -0600306 r.ContentLength = 0
jrperritt655245a2016-08-31 15:30:27 -0500307 default:
jrperritt98d01622017-01-12 14:24:42 -0600308 r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64)
jrperritt655245a2016-08-31 15:30:27 -0500309 if err != nil {
310 return err
311 }
312 }
313
jrperritt98d01622017-01-12 14:24:42 -0600314 r.Date = time.Time(s.Date)
315 r.LastModified = time.Time(s.LastModified)
316
jrperritt655245a2016-08-31 15:30:27 -0500317 return nil
318}
319
Jamie Hannafordc9cdc8f2014-10-06 16:32:56 +0200320// CreateResult represents the result of a create operation.
Jon Perritt5db08922014-09-30 21:32:48 -0500321type CreateResult struct {
Jon Perrittfea90732016-03-15 02:57:05 -0500322 checksum string
Jon Perrittd50f93e2014-10-27 14:19:27 -0500323 gophercloud.HeaderResult
Jon Perritt5db08922014-09-30 21:32:48 -0500324}
325
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700326// Extract will return a struct of headers returned from a call to Create. To obtain
327// a map of headers, call the ExtractHeader method on the CreateResult.
Jon Perritt3c166472016-02-25 03:07:41 -0600328func (r CreateResult) Extract() (*CreateHeader, error) {
Jon Perrittfea90732016-03-15 02:57:05 -0500329 //if r.Header.Get("ETag") != fmt.Sprintf("%x", localChecksum) {
330 // return nil, ErrWrongChecksum{}
331 //}
Jon Perritt3c166472016-02-25 03:07:41 -0600332 var s *CreateHeader
333 err := r.ExtractInto(&s)
334 return s, err
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700335}
336
337// UpdateHeader represents the headers returned in the response from a Update request.
338type UpdateHeader struct {
jrperritt98d01622017-01-12 14:24:42 -0600339 ContentLength int64 `json:"-"`
340 ContentType string `json:"Content-Type"`
341 Date time.Time `json:"-"`
342 TransID string `json:"X-Trans-Id"`
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700343}
344
jrperritt98d01622017-01-12 14:24:42 -0600345func (r *UpdateHeader) UnmarshalJSON(b []byte) error {
jrperritt655245a2016-08-31 15:30:27 -0500346 type tmp UpdateHeader
jrperritt98d01622017-01-12 14:24:42 -0600347 var s struct {
jrperritt655245a2016-08-31 15:30:27 -0500348 tmp
jrperritt98d01622017-01-12 14:24:42 -0600349 ContentLength string `json:"Content-Length"`
350 Date gophercloud.JSONRFC1123 `json:"Date"`
jrperritt655245a2016-08-31 15:30:27 -0500351 }
jrperritt98d01622017-01-12 14:24:42 -0600352 err := json.Unmarshal(b, &s)
jrperritt655245a2016-08-31 15:30:27 -0500353 if err != nil {
354 return err
355 }
356
jrperritt98d01622017-01-12 14:24:42 -0600357 *r = UpdateHeader(s.tmp)
jrperritt655245a2016-08-31 15:30:27 -0500358
jrperritt98d01622017-01-12 14:24:42 -0600359 switch s.ContentLength {
jrperritt655245a2016-08-31 15:30:27 -0500360 case "":
jrperritt98d01622017-01-12 14:24:42 -0600361 r.ContentLength = 0
jrperritt655245a2016-08-31 15:30:27 -0500362 default:
jrperritt98d01622017-01-12 14:24:42 -0600363 r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64)
jrperritt655245a2016-08-31 15:30:27 -0500364 if err != nil {
365 return err
366 }
367 }
368
jrperritt98d01622017-01-12 14:24:42 -0600369 r.Date = time.Time(s.Date)
370
jrperritt655245a2016-08-31 15:30:27 -0500371 return nil
372}
373
Jamie Hannafordc9cdc8f2014-10-06 16:32:56 +0200374// UpdateResult represents the result of an update operation.
Jon Perritt5db08922014-09-30 21:32:48 -0500375type UpdateResult struct {
Jon Perrittd50f93e2014-10-27 14:19:27 -0500376 gophercloud.HeaderResult
Jon Perritt5db08922014-09-30 21:32:48 -0500377}
378
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700379// Extract will return a struct of headers returned from a call to Update. To obtain
380// a map of headers, call the ExtractHeader method on the UpdateResult.
Jon Perritt3c166472016-02-25 03:07:41 -0600381func (r UpdateResult) Extract() (*UpdateHeader, error) {
382 var s *UpdateHeader
383 err := r.ExtractInto(&s)
384 return s, err
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700385}
386
387// DeleteHeader represents the headers returned in the response from a Delete request.
388type DeleteHeader struct {
jrperritt98d01622017-01-12 14:24:42 -0600389 ContentLength int64 `json:"Content-Length"`
390 ContentType string `json:"Content-Type"`
391 Date time.Time `json:"-"`
392 TransID string `json:"X-Trans-Id"`
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700393}
394
jrperritt98d01622017-01-12 14:24:42 -0600395func (r *DeleteHeader) UnmarshalJSON(b []byte) error {
jrperritt655245a2016-08-31 15:30:27 -0500396 type tmp DeleteHeader
jrperritt98d01622017-01-12 14:24:42 -0600397 var s struct {
jrperritt655245a2016-08-31 15:30:27 -0500398 tmp
jrperritt98d01622017-01-12 14:24:42 -0600399 ContentLength string `json:"Content-Length"`
400 Date gophercloud.JSONRFC1123 `json:"Date"`
jrperritt655245a2016-08-31 15:30:27 -0500401 }
jrperritt98d01622017-01-12 14:24:42 -0600402 err := json.Unmarshal(b, &s)
jrperritt655245a2016-08-31 15:30:27 -0500403 if err != nil {
404 return err
405 }
406
jrperritt98d01622017-01-12 14:24:42 -0600407 *r = DeleteHeader(s.tmp)
jrperritt655245a2016-08-31 15:30:27 -0500408
jrperritt98d01622017-01-12 14:24:42 -0600409 switch s.ContentLength {
jrperritt655245a2016-08-31 15:30:27 -0500410 case "":
jrperritt98d01622017-01-12 14:24:42 -0600411 r.ContentLength = 0
jrperritt655245a2016-08-31 15:30:27 -0500412 default:
jrperritt98d01622017-01-12 14:24:42 -0600413 r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64)
jrperritt655245a2016-08-31 15:30:27 -0500414 if err != nil {
415 return err
416 }
417 }
418
jrperritt98d01622017-01-12 14:24:42 -0600419 r.Date = time.Time(s.Date)
420
jrperritt655245a2016-08-31 15:30:27 -0500421 return nil
422}
423
Jamie Hannafordc9cdc8f2014-10-06 16:32:56 +0200424// DeleteResult represents the result of a delete operation.
Jon Perritt5db08922014-09-30 21:32:48 -0500425type DeleteResult struct {
Jon Perrittd50f93e2014-10-27 14:19:27 -0500426 gophercloud.HeaderResult
Jon Perritt5db08922014-09-30 21:32:48 -0500427}
428
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700429// Extract will return a struct of headers returned from a call to Delete. To obtain
430// a map of headers, call the ExtractHeader method on the DeleteResult.
Jon Perritt3c166472016-02-25 03:07:41 -0600431func (r DeleteResult) Extract() (*DeleteHeader, error) {
432 var s *DeleteHeader
433 err := r.ExtractInto(&s)
434 return s, err
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700435}
436
437// CopyHeader represents the headers returned in the response from a Copy request.
438type CopyHeader struct {
jrperritt98d01622017-01-12 14:24:42 -0600439 ContentLength int64 `json:"-"`
440 ContentType string `json:"Content-Type"`
441 CopiedFrom string `json:"X-Copied-From"`
442 CopiedFromLastModified time.Time `json:"-"`
443 Date time.Time `json:"-"`
444 ETag string `json:"Etag"`
445 LastModified time.Time `json:"-"`
446 TransID string `json:"X-Trans-Id"`
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700447}
448
jrperritt98d01622017-01-12 14:24:42 -0600449func (r *CopyHeader) UnmarshalJSON(b []byte) error {
jrperritt655245a2016-08-31 15:30:27 -0500450 type tmp CopyHeader
jrperritt98d01622017-01-12 14:24:42 -0600451 var s struct {
jrperritt655245a2016-08-31 15:30:27 -0500452 tmp
jrperritt98d01622017-01-12 14:24:42 -0600453 ContentLength string `json:"Content-Length"`
454 CopiedFromLastModified gophercloud.JSONRFC1123 `json:"X-Copied-From-Last-Modified"`
455 Date gophercloud.JSONRFC1123 `json:"Date"`
456 LastModified gophercloud.JSONRFC1123 `json:"Last-Modified"`
jrperritt655245a2016-08-31 15:30:27 -0500457 }
jrperritt98d01622017-01-12 14:24:42 -0600458 err := json.Unmarshal(b, &s)
jrperritt655245a2016-08-31 15:30:27 -0500459 if err != nil {
460 return err
461 }
462
jrperritt98d01622017-01-12 14:24:42 -0600463 *r = CopyHeader(s.tmp)
jrperritt655245a2016-08-31 15:30:27 -0500464
jrperritt98d01622017-01-12 14:24:42 -0600465 switch s.ContentLength {
jrperritt655245a2016-08-31 15:30:27 -0500466 case "":
jrperritt98d01622017-01-12 14:24:42 -0600467 r.ContentLength = 0
jrperritt655245a2016-08-31 15:30:27 -0500468 default:
jrperritt98d01622017-01-12 14:24:42 -0600469 r.ContentLength, err = strconv.ParseInt(s.ContentLength, 10, 64)
jrperritt655245a2016-08-31 15:30:27 -0500470 if err != nil {
471 return err
472 }
473 }
474
jrperritt98d01622017-01-12 14:24:42 -0600475 r.Date = time.Time(s.Date)
476 r.CopiedFromLastModified = time.Time(s.CopiedFromLastModified)
477 r.LastModified = time.Time(s.LastModified)
478
jrperritt655245a2016-08-31 15:30:27 -0500479 return nil
480}
481
Jamie Hannafordc9cdc8f2014-10-06 16:32:56 +0200482// CopyResult represents the result of a copy operation.
Jon Perritt5db08922014-09-30 21:32:48 -0500483type CopyResult struct {
Jon Perrittd50f93e2014-10-27 14:19:27 -0500484 gophercloud.HeaderResult
Jon Perritt5db08922014-09-30 21:32:48 -0500485}
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700486
487// Extract will return a struct of headers returned from a call to Copy. To obtain
488// a map of headers, call the ExtractHeader method on the CopyResult.
Jon Perritt3c166472016-02-25 03:07:41 -0600489func (r CopyResult) Extract() (*CopyHeader, error) {
490 var s *CopyHeader
491 err := r.ExtractInto(&s)
492 return s, err
Jon Perritt8c31b2a2014-12-03 10:21:11 -0700493}