blob: bc2149601bd8aa66296e79c05a74f9a390ebee30 [file] [log] [blame]
Jon Perritt816d2a02014-03-11 20:49:46 -05001package objects
2
3import (
4 "fmt"
Jon Perritt8c93a302014-09-28 22:35:57 -05005 "io"
6 "time"
Ash Wilson604320e2014-09-10 16:02:28 -04007
8 "github.com/racker/perigee"
9 "github.com/rackspace/gophercloud"
Ash Wilsonca6f7562014-09-16 15:43:54 -040010 "github.com/rackspace/gophercloud/pagination"
Jon Perritt816d2a02014-03-11 20:49:46 -050011)
12
Jon Perritt8c93a302014-09-28 22:35:57 -050013// ListOpts is a structure that holds parameters for listing objects.
14type ListOpts struct {
15 Full bool
16 Limit int `q:"limit"`
17 Marker string `q:"marker"`
18 EndMarker string `q:"end_marker"`
19 Format string `q:"format"`
20 Prefix string `q:"prefix"`
21 Delimiter [1]byte `q:"delimiter"`
22 Path string `q:"path"`
Ash Wilsonca6f7562014-09-16 15:43:54 -040023}
24
Jon Perritt816d2a02014-03-11 20:49:46 -050025// List is a function that retrieves all objects in a container. It also returns the details
26// for the container. To extract only the object information or names, pass the ListResult
Jon Perritteb575642014-04-24 15:16:31 -050027// response to the ExtractInfo or ExtractNames function, respectively.
Jon Perrittde47eac2014-09-30 15:34:17 -050028func List(c *gophercloud.ServiceClient, containerName string, opts *ListOpts) pagination.Pager {
Ash Wilsonca6f7562014-09-16 15:43:54 -040029 var headers map[string]string
Jon Perritt816d2a02014-03-11 20:49:46 -050030
Jon Perrittde47eac2014-09-30 15:34:17 -050031 url := containerURL(c, containerName)
32 if opts != nil {
33 query, err := gophercloud.BuildQueryString(opts)
34 if err != nil {
35 fmt.Printf("Error building query string: %v", err)
36 return pagination.Pager{Err: err}
37 }
38 url += query.String()
Jon Perritt816d2a02014-03-11 20:49:46 -050039
Jon Perrittde47eac2014-09-30 15:34:17 -050040 if !opts.Full {
41 headers = map[string]string{"Accept": "text/plain", "Content-Type": "text/plain"}
42 }
Jon Perritt5db08922014-09-30 21:32:48 -050043 } else {
44 headers = map[string]string{"Accept": "text/plain", "Content-Type": "text/plain"}
Ash Wilsonca6f7562014-09-16 15:43:54 -040045 }
46
47 createPage := func(r pagination.LastHTTPResponse) pagination.Page {
Jon Perritt8c93a302014-09-28 22:35:57 -050048 p := ObjectPage{pagination.MarkerPageBase{LastHTTPResponse: r}}
Ash Wilsonca6f7562014-09-16 15:43:54 -040049 p.MarkerPageBase.Owner = p
50 return p
Jon Perritt816d2a02014-03-11 20:49:46 -050051 }
52
Ash Wilsonca6f7562014-09-16 15:43:54 -040053 pager := pagination.NewPager(c, url, createPage)
54 pager.Headers = headers
55 return pager
Jon Perritt816d2a02014-03-11 20:49:46 -050056}
57
Jon Perritt8c93a302014-09-28 22:35:57 -050058// DownloadOpts is a structure that holds parameters for downloading an object.
59type DownloadOpts struct {
60 IfMatch string `h:"If-Match"`
61 IfModifiedSince time.Time `h:"If-Modified-Since"`
62 IfNoneMatch string `h:"If-None-Match"`
63 IfUnmodifiedSince time.Time `h:"If-Unmodified-Since"`
64 Range string `h:"Range"`
65 Expires string `q:"expires"`
66 MultipartManifest string `q:"multipart-manifest"`
67 Signature string `q:"signature"`
68}
69
Jon Perritt816d2a02014-03-11 20:49:46 -050070// Download is a function that retrieves the content and metadata for an object.
Jon Perritteb575642014-04-24 15:16:31 -050071// To extract just the content, pass the DownloadResult response to the ExtractContent
Jon Perritt816d2a02014-03-11 20:49:46 -050072// function.
Jon Perrittde47eac2014-09-30 15:34:17 -050073func Download(c *gophercloud.ServiceClient, containerName, objectName string, opts *DownloadOpts) DownloadResult {
Jon Perritt5db08922014-09-30 21:32:48 -050074 var res DownloadResult
Jon Perritt8c93a302014-09-28 22:35:57 -050075
Jon Perrittde47eac2014-09-30 15:34:17 -050076 url := objectURL(c, containerName, objectName)
Ash Wilson604320e2014-09-10 16:02:28 -040077 h := c.Provider.AuthenticatedHeaders()
Jon Perritt816d2a02014-03-11 20:49:46 -050078
Jon Perrittde47eac2014-09-30 15:34:17 -050079 if opts != nil {
80 headers, err := gophercloud.BuildHeaders(opts)
81 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -050082 res.Err = err
83 return res
Jon Perrittde47eac2014-09-30 15:34:17 -050084 }
85
86 for k, v := range headers {
87 h[k] = v
88 }
89
90 query, err := gophercloud.BuildQueryString(opts)
91 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -050092 res.Err = err
93 return res
Jon Perrittde47eac2014-09-30 15:34:17 -050094 }
95 url += query.String()
Jon Perritt8c93a302014-09-28 22:35:57 -050096 }
97
Jon Perritt816d2a02014-03-11 20:49:46 -050098 resp, err := perigee.Request("GET", url, perigee.Options{
Jon Perritt816d2a02014-03-11 20:49:46 -050099 MoreHeaders: h,
Ash Wilsone47ea9e2014-09-10 16:03:44 -0400100 OkCodes: []int{200},
Jon Perritt816d2a02014-03-11 20:49:46 -0500101 })
Jon Perritt5db08922014-09-30 21:32:48 -0500102 res.Err = err
103 res.Resp = &resp.HttpResponse
104 return res
Jon Perritt8c93a302014-09-28 22:35:57 -0500105}
106
107// CreateOpts is a structure that holds parameters for creating an object.
108type CreateOpts struct {
109 Metadata map[string]string
110 ContentDisposition string `h:"Content-Disposition"`
111 ContentEncoding string `h:"Content-Encoding"`
112 ContentLength int `h:"Content-Length"`
113 ContentType string `h:"Content-Type"`
114 CopyFrom string `h:"X-Copy-From"`
115 DeleteAfter int `h:"X-Delete-After"`
116 DeleteAt int `h:"X-Delete-At"`
117 DetectContentType string `h:"X-Detect-Content-Type"`
118 ETag string `h:"ETag"`
119 IfNoneMatch string `h:"If-None-Match"`
120 ObjectManifest string `h:"X-Object-Manifest"`
121 TransferEncoding string `h:"Transfer-Encoding"`
122 Expires string `q:"expires"`
123 MultipartManifest string `q:"multiple-manifest"`
124 Signature string `q:"signature"`
Jon Perritt816d2a02014-03-11 20:49:46 -0500125}
126
127// Create is a function that creates a new object or replaces an existing object.
Jon Perritt5db08922014-09-30 21:32:48 -0500128func Create(c *gophercloud.ServiceClient, containerName, objectName string, content io.Reader, opts *CreateOpts) CreateResult {
129 var res CreateResult
Jon Perritt816d2a02014-03-11 20:49:46 -0500130 var reqBody []byte
131
Jon Perrittde47eac2014-09-30 15:34:17 -0500132 url := objectURL(c, containerName, objectName)
Ash Wilson604320e2014-09-10 16:02:28 -0400133 h := c.Provider.AuthenticatedHeaders()
Jon Perritt816d2a02014-03-11 20:49:46 -0500134
Jon Perrittde47eac2014-09-30 15:34:17 -0500135 if opts != nil {
136 headers, err := gophercloud.BuildHeaders(opts)
137 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500138 res.Err = err
139 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500140 }
Jon Perritt8c93a302014-09-28 22:35:57 -0500141
Jon Perrittde47eac2014-09-30 15:34:17 -0500142 for k, v := range headers {
143 h[k] = v
144 }
Jon Perritt816d2a02014-03-11 20:49:46 -0500145
Jon Perrittde47eac2014-09-30 15:34:17 -0500146 for k, v := range opts.Metadata {
147 h["X-Object-Meta-"+k] = v
148 }
Jon Perritt816d2a02014-03-11 20:49:46 -0500149
Jon Perrittde47eac2014-09-30 15:34:17 -0500150 query, err := gophercloud.BuildQueryString(opts)
151 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500152 res.Err = err
153 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500154 }
Jon Perritt5db08922014-09-30 21:32:48 -0500155
Jon Perrittde47eac2014-09-30 15:34:17 -0500156 url += query.String()
Jon Perritt8c93a302014-09-28 22:35:57 -0500157 }
Jon Perritt816d2a02014-03-11 20:49:46 -0500158
Jon Perritt816d2a02014-03-11 20:49:46 -0500159 if content != nil {
Jon Perritt884e0312014-08-14 17:25:38 -0500160 reqBody = make([]byte, 0)
Ash Wilson604320e2014-09-10 16:02:28 -0400161 _, err := content.Read(reqBody)
Jon Perritt816d2a02014-03-11 20:49:46 -0500162 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500163 res.Err = err
164 return res
Jon Perritt816d2a02014-03-11 20:49:46 -0500165 }
166 }
167
Jon Perritt5db08922014-09-30 21:32:48 -0500168 resp, err := perigee.Request("PUT", url, perigee.Options{
Jon Perritt816d2a02014-03-11 20:49:46 -0500169 ReqBody: reqBody,
170 MoreHeaders: h,
Ash Wilsone47ea9e2014-09-10 16:03:44 -0400171 OkCodes: []int{201},
Jon Perritt816d2a02014-03-11 20:49:46 -0500172 })
Jon Perritt5db08922014-09-30 21:32:48 -0500173 res.Resp = &resp.HttpResponse
174 res.Err = err
175 return res
Jon Perritt816d2a02014-03-11 20:49:46 -0500176}
177
Jon Perritt8c93a302014-09-28 22:35:57 -0500178// CopyOpts is a structure that holds parameters for copying one object to another.
179type CopyOpts struct {
180 Metadata map[string]string
181 ContentDisposition string `h:"Content-Disposition"`
182 ContentEncoding string `h:"Content-Encoding"`
183 ContentType string `h:"Content-Type"`
184 Destination string `h:"Destination,required"`
185}
186
Jon Perritt816d2a02014-03-11 20:49:46 -0500187// Copy is a function that copies one object to another.
Jon Perritt5db08922014-09-30 21:32:48 -0500188func Copy(c *gophercloud.ServiceClient, containerName, objectName string, opts *CopyOpts) CopyResult {
189 var res CopyResult
Ash Wilson604320e2014-09-10 16:02:28 -0400190 h := c.Provider.AuthenticatedHeaders()
Jon Perritt816d2a02014-03-11 20:49:46 -0500191
Jon Perrittde47eac2014-09-30 15:34:17 -0500192 if opts == nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500193 res.Err = fmt.Errorf("Required CopyOpts field 'Destination' not set.")
194 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500195 }
Jon Perritt8c93a302014-09-28 22:35:57 -0500196 headers, err := gophercloud.BuildHeaders(opts)
197 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500198 res.Err = err
199 return res
Jon Perritt816d2a02014-03-11 20:49:46 -0500200 }
Jon Perritt8c93a302014-09-28 22:35:57 -0500201 for k, v := range headers {
Jon Perritt816d2a02014-03-11 20:49:46 -0500202 h[k] = v
203 }
204
205 for k, v := range opts.Metadata {
206 h["X-Object-Meta-"+k] = v
207 }
208
Jon Perritt8c93a302014-09-28 22:35:57 -0500209 url := objectURL(c, containerName, objectName)
Jon Perritt5db08922014-09-30 21:32:48 -0500210 resp, err := perigee.Request("COPY", url, perigee.Options{
Jon Perritt8c93a302014-09-28 22:35:57 -0500211 MoreHeaders: h,
212 OkCodes: []int{201},
213 })
Jon Perritt5db08922014-09-30 21:32:48 -0500214 res.Resp = &resp.HttpResponse
215 return res
Jon Perritt8c93a302014-09-28 22:35:57 -0500216}
217
218// DeleteOpts is a structure that holds parameters for deleting an object.
219type DeleteOpts struct {
220 MultipartManifest string `q:"multipart-manifest"`
221}
222
223// Delete is a function that deletes an object.
Jon Perritt5db08922014-09-30 21:32:48 -0500224func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts *DeleteOpts) DeleteResult {
225 var res DeleteResult
Jon Perrittde47eac2014-09-30 15:34:17 -0500226 url := objectURL(c, containerName, objectName)
Jon Perritt8c93a302014-09-28 22:35:57 -0500227
Jon Perrittde47eac2014-09-30 15:34:17 -0500228 if opts != nil {
229 query, err := gophercloud.BuildQueryString(opts)
230 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500231 res.Err = err
232 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500233 }
234 url += query.String()
Jon Perritt8c93a302014-09-28 22:35:57 -0500235 }
236
Jon Perritt5db08922014-09-30 21:32:48 -0500237 resp, err := perigee.Request("DELETE", url, perigee.Options{
Jon Perrittde47eac2014-09-30 15:34:17 -0500238 MoreHeaders: c.Provider.AuthenticatedHeaders(),
Jon Perritt8c93a302014-09-28 22:35:57 -0500239 OkCodes: []int{204},
240 })
Jon Perritt5db08922014-09-30 21:32:48 -0500241 res.Resp = &resp.HttpResponse
242 res.Err = err
243 return res
Jon Perritt8c93a302014-09-28 22:35:57 -0500244}
245
246// GetOpts is a structure that holds parameters for getting an object's metadata.
247type GetOpts struct {
248 Expires string `q:"expires"`
249 Signature string `q:"signature"`
250}
251
252// Get is a function that retrieves the metadata of an object. To extract just the custom
253// metadata, pass the GetResult response to the ExtractMetadata function.
Jon Perrittde47eac2014-09-30 15:34:17 -0500254func Get(c *gophercloud.ServiceClient, containerName, objectName string, opts *GetOpts) GetResult {
Jon Perritt5db08922014-09-30 21:32:48 -0500255 var res GetResult
Jon Perrittde47eac2014-09-30 15:34:17 -0500256 url := objectURL(c, containerName, objectName)
257
258 if opts != nil {
259 query, err := gophercloud.BuildQueryString(opts)
260 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500261 res.Err = err
262 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500263 }
264 url += query.String()
Jon Perritt8c93a302014-09-28 22:35:57 -0500265 }
266
Jon Perritt8c93a302014-09-28 22:35:57 -0500267 resp, err := perigee.Request("HEAD", url, perigee.Options{
268 MoreHeaders: c.Provider.AuthenticatedHeaders(),
269 OkCodes: []int{200, 204},
270 })
Jon Perritt5db08922014-09-30 21:32:48 -0500271 res.Err = err
272 res.Resp = &resp.HttpResponse
273 return res
Jon Perritt8c93a302014-09-28 22:35:57 -0500274}
275
276// UpdateOpts is a structure that holds parameters for updating, creating, or deleting an
277// object's metadata.
278type UpdateOpts struct {
279 Metadata map[string]string
280 ContentDisposition string `h:"Content-Disposition"`
281 ContentEncoding string `h:"Content-Encoding"`
282 ContentType string `h:"Content-Type"`
283 DeleteAfter int `h:"X-Delete-After"`
284 DeleteAt int `h:"X-Delete-At"`
285 DetectContentType bool `h:"X-Detect-Content-Type"`
286}
287
288// Update is a function that creates, updates, or deletes an object's metadata.
Jon Perritt5db08922014-09-30 21:32:48 -0500289func Update(c *gophercloud.ServiceClient, containerName, objectName string, opts *UpdateOpts) UpdateResult {
290 var res UpdateResult
Jon Perritt8c93a302014-09-28 22:35:57 -0500291 h := c.Provider.AuthenticatedHeaders()
292
Jon Perrittde47eac2014-09-30 15:34:17 -0500293 if opts != nil {
294 headers, err := gophercloud.BuildHeaders(opts)
295 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500296 res.Err = err
297 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500298 }
Jon Perritt8c93a302014-09-28 22:35:57 -0500299
Jon Perrittde47eac2014-09-30 15:34:17 -0500300 for k, v := range headers {
301 h[k] = v
302 }
Jon Perritt8c93a302014-09-28 22:35:57 -0500303
Jon Perrittde47eac2014-09-30 15:34:17 -0500304 for k, v := range opts.Metadata {
305 h["X-Object-Meta-"+k] = v
306 }
Jon Perritt8c93a302014-09-28 22:35:57 -0500307 }
308
309 url := objectURL(c, containerName, objectName)
Jon Perritt5db08922014-09-30 21:32:48 -0500310 resp, err := perigee.Request("POST", url, perigee.Options{
Jon Perritt816d2a02014-03-11 20:49:46 -0500311 MoreHeaders: h,
Ash Wilsone47ea9e2014-09-10 16:03:44 -0400312 OkCodes: []int{202},
Jon Perritt816d2a02014-03-11 20:49:46 -0500313 })
Jon Perritt5db08922014-09-30 21:32:48 -0500314 res.Resp = &resp.HttpResponse
315 res.Err = err
316 return res
Jon Perritt816d2a02014-03-11 20:49:46 -0500317}