blob: 1b6cb5c6aa61a83a4b6e47315864473807f822b2 [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"
Ash Wilsonaf262872014-10-20 09:32:29 -04006 "io/ioutil"
Jon Perritt8c93a302014-09-28 22:35:57 -05007 "time"
Ash Wilson604320e2014-09-10 16:02:28 -04008
9 "github.com/racker/perigee"
10 "github.com/rackspace/gophercloud"
Ash Wilsonca6f7562014-09-16 15:43:54 -040011 "github.com/rackspace/gophercloud/pagination"
Jon Perritt816d2a02014-03-11 20:49:46 -050012)
13
Jon Perritte90aced2014-10-12 23:24:06 -050014// ListOptsBuilder allows extensions to add additional parameters to the List
15// request.
16type ListOptsBuilder interface {
17 ToObjectListParams() (bool, string, error)
18}
19
Jon Perritt8c93a302014-09-28 22:35:57 -050020// ListOpts is a structure that holds parameters for listing objects.
21type ListOpts struct {
22 Full bool
Jon Perritt04851d32014-10-14 02:07:13 -050023 Limit int `q:"limit"`
24 Marker string `q:"marker"`
25 EndMarker string `q:"end_marker"`
26 Format string `q:"format"`
27 Prefix string `q:"prefix"`
28 Delimiter string `q:"delimiter"`
29 Path string `q:"path"`
Ash Wilsonca6f7562014-09-16 15:43:54 -040030}
31
Jon Perritte90aced2014-10-12 23:24:06 -050032// ToObjectListParams formats a ListOpts into a query string and boolean
33// representing whether to list complete information for each object.
34func (opts ListOpts) ToObjectListParams() (bool, string, error) {
35 q, err := gophercloud.BuildQueryString(opts)
36 if err != nil {
37 return false, "", err
38 }
39 return opts.Full, q.String(), nil
40}
41
Jon Perritt816d2a02014-03-11 20:49:46 -050042// List is a function that retrieves all objects in a container. It also returns the details
43// for the container. To extract only the object information or names, pass the ListResult
Jon Perritteb575642014-04-24 15:16:31 -050044// response to the ExtractInfo or ExtractNames function, respectively.
Jon Perritte90aced2014-10-12 23:24:06 -050045func List(c *gophercloud.ServiceClient, containerName string, opts ListOptsBuilder) pagination.Pager {
46 headers := map[string]string{"Accept": "text/plain", "Content-Type": "text/plain"}
Jon Perritt816d2a02014-03-11 20:49:46 -050047
Jon Perrittea4e3012014-10-09 22:03:19 -050048 url := listURL(c, containerName)
Jon Perrittde47eac2014-09-30 15:34:17 -050049 if opts != nil {
Jon Perritte90aced2014-10-12 23:24:06 -050050 full, query, err := opts.ToObjectListParams()
Jon Perrittde47eac2014-09-30 15:34:17 -050051 if err != nil {
52 fmt.Printf("Error building query string: %v", err)
53 return pagination.Pager{Err: err}
54 }
Jon Perritte90aced2014-10-12 23:24:06 -050055 url += query
Jon Perritt816d2a02014-03-11 20:49:46 -050056
Jon Perritte90aced2014-10-12 23:24:06 -050057 if full {
58 headers = map[string]string{"Accept": "application/json", "Content-Type": "application/json"}
Jon Perrittde47eac2014-09-30 15:34:17 -050059 }
Ash Wilsonca6f7562014-09-16 15:43:54 -040060 }
61
Ash Wilsonb8b16f82014-10-20 10:19:49 -040062 createPage := func(r pagination.PageResult) pagination.Page {
63 p := ObjectPage{pagination.MarkerPageBase{PageResult: r}}
Ash Wilsonca6f7562014-09-16 15:43:54 -040064 p.MarkerPageBase.Owner = p
65 return p
Jon Perritt816d2a02014-03-11 20:49:46 -050066 }
67
Ash Wilsonca6f7562014-09-16 15:43:54 -040068 pager := pagination.NewPager(c, url, createPage)
69 pager.Headers = headers
70 return pager
Jon Perritt816d2a02014-03-11 20:49:46 -050071}
72
Jon Perritte90aced2014-10-12 23:24:06 -050073// DownloadOptsBuilder allows extensions to add additional parameters to the
74// Download request.
75type DownloadOptsBuilder interface {
76 ToObjectDownloadParams() (map[string]string, string, error)
77}
78
Jon Perritt8c93a302014-09-28 22:35:57 -050079// DownloadOpts is a structure that holds parameters for downloading an object.
80type DownloadOpts struct {
81 IfMatch string `h:"If-Match"`
82 IfModifiedSince time.Time `h:"If-Modified-Since"`
83 IfNoneMatch string `h:"If-None-Match"`
84 IfUnmodifiedSince time.Time `h:"If-Unmodified-Since"`
85 Range string `h:"Range"`
86 Expires string `q:"expires"`
87 MultipartManifest string `q:"multipart-manifest"`
88 Signature string `q:"signature"`
89}
90
Jon Perritte90aced2014-10-12 23:24:06 -050091// ToObjectDownloadParams formats a DownloadOpts into a query string and map of
92// headers.
93func (opts ListOpts) ToObjectDownloadParams() (map[string]string, string, error) {
94 q, err := gophercloud.BuildQueryString(opts)
95 if err != nil {
96 return nil, "", err
97 }
98 h, err := gophercloud.BuildHeaders(opts)
99 if err != nil {
100 return nil, q.String(), err
101 }
102 return h, q.String(), nil
103}
104
Jon Perritt816d2a02014-03-11 20:49:46 -0500105// Download is a function that retrieves the content and metadata for an object.
Jon Perritte90aced2014-10-12 23:24:06 -0500106// To extract just the content, pass the DownloadResult response to the
107// ExtractContent function.
108func Download(c *gophercloud.ServiceClient, containerName, objectName string, opts DownloadOptsBuilder) DownloadResult {
Jon Perritt5db08922014-09-30 21:32:48 -0500109 var res DownloadResult
Jon Perritt8c93a302014-09-28 22:35:57 -0500110
Jon Perrittea4e3012014-10-09 22:03:19 -0500111 url := downloadURL(c, containerName, objectName)
Ash Wilson77857dc2014-10-22 09:09:02 -0400112 h := c.AuthenticatedHeaders()
Jon Perritt816d2a02014-03-11 20:49:46 -0500113
Jon Perrittde47eac2014-09-30 15:34:17 -0500114 if opts != nil {
Jon Perritte90aced2014-10-12 23:24:06 -0500115 headers, query, err := opts.ToObjectDownloadParams()
Jon Perrittde47eac2014-09-30 15:34:17 -0500116 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500117 res.Err = err
118 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500119 }
120
121 for k, v := range headers {
122 h[k] = v
123 }
124
Jon Perritte90aced2014-10-12 23:24:06 -0500125 url += query
Jon Perritt8c93a302014-09-28 22:35:57 -0500126 }
127
Jon Perritt816d2a02014-03-11 20:49:46 -0500128 resp, err := perigee.Request("GET", url, perigee.Options{
Jon Perritt816d2a02014-03-11 20:49:46 -0500129 MoreHeaders: h,
Ash Wilsone47ea9e2014-09-10 16:03:44 -0400130 OkCodes: []int{200},
Jon Perritt816d2a02014-03-11 20:49:46 -0500131 })
Ash Wilsonaf262872014-10-20 09:32:29 -0400132 defer resp.HttpResponse.Body.Close()
133 body, err := ioutil.ReadAll(resp.HttpResponse.Body)
Ash Wilsond3dc2542014-10-20 10:10:48 -0400134 res.Body = body
Jon Perritt5db08922014-09-30 21:32:48 -0500135 res.Err = err
Ash Wilson72e4d2c2014-10-20 10:27:30 -0400136 res.Header = resp.HttpResponse.Header
Jon Perritt5db08922014-09-30 21:32:48 -0500137 return res
Jon Perritt8c93a302014-09-28 22:35:57 -0500138}
139
Jon Perritte90aced2014-10-12 23:24:06 -0500140// CreateOptsBuilder allows extensions to add additional parameters to the
141// Create request.
142type CreateOptsBuilder interface {
143 ToObjectCreateParams() (map[string]string, string, error)
144}
145
Jon Perritt8c93a302014-09-28 22:35:57 -0500146// CreateOpts is a structure that holds parameters for creating an object.
147type CreateOpts struct {
148 Metadata map[string]string
149 ContentDisposition string `h:"Content-Disposition"`
150 ContentEncoding string `h:"Content-Encoding"`
151 ContentLength int `h:"Content-Length"`
152 ContentType string `h:"Content-Type"`
153 CopyFrom string `h:"X-Copy-From"`
154 DeleteAfter int `h:"X-Delete-After"`
155 DeleteAt int `h:"X-Delete-At"`
156 DetectContentType string `h:"X-Detect-Content-Type"`
157 ETag string `h:"ETag"`
158 IfNoneMatch string `h:"If-None-Match"`
159 ObjectManifest string `h:"X-Object-Manifest"`
160 TransferEncoding string `h:"Transfer-Encoding"`
161 Expires string `q:"expires"`
162 MultipartManifest string `q:"multiple-manifest"`
163 Signature string `q:"signature"`
Jon Perritt816d2a02014-03-11 20:49:46 -0500164}
165
Jon Perritte90aced2014-10-12 23:24:06 -0500166// ToObjectCreateParams formats a CreateOpts into a query string and map of
167// headers.
168func (opts CreateOpts) ToObjectCreateParams() (map[string]string, string, error) {
169 q, err := gophercloud.BuildQueryString(opts)
170 if err != nil {
171 return nil, "", err
172 }
173 h, err := gophercloud.BuildHeaders(opts)
174 if err != nil {
175 return nil, q.String(), err
176 }
177
178 for k, v := range opts.Metadata {
179 h["X-Object-Meta-"+k] = v
180 }
181
182 return h, q.String(), nil
183}
184
Jon Perritt816d2a02014-03-11 20:49:46 -0500185// Create is a function that creates a new object or replaces an existing object.
Jon Perritte90aced2014-10-12 23:24:06 -0500186func Create(c *gophercloud.ServiceClient, containerName, objectName string, content io.Reader, opts CreateOptsBuilder) CreateResult {
Jon Perritt5db08922014-09-30 21:32:48 -0500187 var res CreateResult
Jon Perritt816d2a02014-03-11 20:49:46 -0500188
Jon Perrittea4e3012014-10-09 22:03:19 -0500189 url := createURL(c, containerName, objectName)
Ash Wilson77857dc2014-10-22 09:09:02 -0400190 h := c.AuthenticatedHeaders()
Jon Perritt816d2a02014-03-11 20:49:46 -0500191
Jon Perrittde47eac2014-09-30 15:34:17 -0500192 if opts != nil {
Jon Perritte90aced2014-10-12 23:24:06 -0500193 headers, query, err := opts.ToObjectCreateParams()
Jon Perrittde47eac2014-09-30 15:34:17 -0500194 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500195 res.Err = err
196 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500197 }
Jon Perritt8c93a302014-09-28 22:35:57 -0500198
Jon Perrittde47eac2014-09-30 15:34:17 -0500199 for k, v := range headers {
200 h[k] = v
201 }
Jon Perritt816d2a02014-03-11 20:49:46 -0500202
Jon Perritte90aced2014-10-12 23:24:06 -0500203 url += query
Jon Perritt8c93a302014-09-28 22:35:57 -0500204 }
Jon Perritt816d2a02014-03-11 20:49:46 -0500205
Jon Perritta77ba0d2014-10-17 01:15:29 -0500206 contentType := h["Content-Type"]
Jon Perritt816d2a02014-03-11 20:49:46 -0500207
Jon Perritt5db08922014-09-30 21:32:48 -0500208 resp, err := perigee.Request("PUT", url, perigee.Options{
Jon Perritta77ba0d2014-10-17 01:15:29 -0500209 ContentType: contentType,
210 ReqBody: content,
Jon Perritt816d2a02014-03-11 20:49:46 -0500211 MoreHeaders: h,
Jon Perritta77ba0d2014-10-17 01:15:29 -0500212 OkCodes: []int{201, 202},
Jon Perritt816d2a02014-03-11 20:49:46 -0500213 })
Ash Wilson72e4d2c2014-10-20 10:27:30 -0400214 res.Header = resp.HttpResponse.Header
Jon Perritt5db08922014-09-30 21:32:48 -0500215 res.Err = err
216 return res
Jon Perritt816d2a02014-03-11 20:49:46 -0500217}
218
Jon Perritte90aced2014-10-12 23:24:06 -0500219// CopyOptsBuilder allows extensions to add additional parameters to the
220// Copy request.
221type CopyOptsBuilder interface {
Jon Perritt04851d32014-10-14 02:07:13 -0500222 ToObjectCopyMap() (map[string]string, error)
Jon Perritte90aced2014-10-12 23:24:06 -0500223}
224
225// CopyOpts is a structure that holds parameters for copying one object to
226// another.
Jon Perritt8c93a302014-09-28 22:35:57 -0500227type CopyOpts struct {
228 Metadata map[string]string
229 ContentDisposition string `h:"Content-Disposition"`
230 ContentEncoding string `h:"Content-Encoding"`
231 ContentType string `h:"Content-Type"`
232 Destination string `h:"Destination,required"`
233}
234
Jon Perritt04851d32014-10-14 02:07:13 -0500235// ToObjectCopyMap formats a CopyOpts into a map of headers.
236func (opts CopyOpts) ToObjectCopyMap() (map[string]string, error) {
Jon Perritte90aced2014-10-12 23:24:06 -0500237 if opts.Destination == "" {
238 return nil, fmt.Errorf("Required CopyOpts field 'Destination' not set.")
239 }
240 h, err := gophercloud.BuildHeaders(opts)
241 if err != nil {
242 return nil, err
243 }
244 for k, v := range opts.Metadata {
245 h["X-Object-Meta-"+k] = v
246 }
247 return h, nil
248}
249
Jon Perritt816d2a02014-03-11 20:49:46 -0500250// Copy is a function that copies one object to another.
Jon Perritte90aced2014-10-12 23:24:06 -0500251func Copy(c *gophercloud.ServiceClient, containerName, objectName string, opts CopyOptsBuilder) CopyResult {
Jon Perritt5db08922014-09-30 21:32:48 -0500252 var res CopyResult
Ash Wilson77857dc2014-10-22 09:09:02 -0400253 h := c.AuthenticatedHeaders()
Jon Perritt816d2a02014-03-11 20:49:46 -0500254
Jon Perritt04851d32014-10-14 02:07:13 -0500255 headers, err := opts.ToObjectCopyMap()
Jon Perritt8c93a302014-09-28 22:35:57 -0500256 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500257 res.Err = err
258 return res
Jon Perritt816d2a02014-03-11 20:49:46 -0500259 }
Jon Perritte90aced2014-10-12 23:24:06 -0500260
Jon Perritt8c93a302014-09-28 22:35:57 -0500261 for k, v := range headers {
Jon Perritt816d2a02014-03-11 20:49:46 -0500262 h[k] = v
263 }
264
Jon Perrittea4e3012014-10-09 22:03:19 -0500265 url := copyURL(c, containerName, objectName)
Jon Perritt5db08922014-09-30 21:32:48 -0500266 resp, err := perigee.Request("COPY", url, perigee.Options{
Jon Perritt8c93a302014-09-28 22:35:57 -0500267 MoreHeaders: h,
268 OkCodes: []int{201},
269 })
Ash Wilson72e4d2c2014-10-20 10:27:30 -0400270 res.Header = resp.HttpResponse.Header
Jon Perritt5db08922014-09-30 21:32:48 -0500271 return res
Jon Perritt8c93a302014-09-28 22:35:57 -0500272}
273
Jon Perritte90aced2014-10-12 23:24:06 -0500274// DeleteOptsBuilder allows extensions to add additional parameters to the
275// Delete request.
276type DeleteOptsBuilder interface {
Jon Perritt26780d52014-10-14 11:35:58 -0500277 ToObjectDeleteQuery() (string, error)
Jon Perritte90aced2014-10-12 23:24:06 -0500278}
279
Jon Perritt8c93a302014-09-28 22:35:57 -0500280// DeleteOpts is a structure that holds parameters for deleting an object.
281type DeleteOpts struct {
282 MultipartManifest string `q:"multipart-manifest"`
283}
284
Jon Perritt26780d52014-10-14 11:35:58 -0500285// ToObjectDeleteQuery formats a DeleteOpts into a query string.
286func (opts DeleteOpts) ToObjectDeleteQuery() (string, error) {
Jon Perritte90aced2014-10-12 23:24:06 -0500287 q, err := gophercloud.BuildQueryString(opts)
288 if err != nil {
289 return "", err
290 }
291 return q.String(), nil
292}
293
Jon Perritt8c93a302014-09-28 22:35:57 -0500294// Delete is a function that deletes an object.
Jon Perritte90aced2014-10-12 23:24:06 -0500295func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts DeleteOptsBuilder) DeleteResult {
Jon Perritt5db08922014-09-30 21:32:48 -0500296 var res DeleteResult
Jon Perrittea4e3012014-10-09 22:03:19 -0500297 url := deleteURL(c, containerName, objectName)
Jon Perritt8c93a302014-09-28 22:35:57 -0500298
Jon Perrittde47eac2014-09-30 15:34:17 -0500299 if opts != nil {
Jon Perritt26780d52014-10-14 11:35:58 -0500300 query, err := opts.ToObjectDeleteQuery()
Jon Perrittde47eac2014-09-30 15:34:17 -0500301 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500302 res.Err = err
303 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500304 }
Jon Perritte90aced2014-10-12 23:24:06 -0500305 url += query
Jon Perritt8c93a302014-09-28 22:35:57 -0500306 }
307
Jon Perritt5db08922014-09-30 21:32:48 -0500308 resp, err := perigee.Request("DELETE", url, perigee.Options{
Ash Wilson77857dc2014-10-22 09:09:02 -0400309 MoreHeaders: c.AuthenticatedHeaders(),
Jon Perritt8c93a302014-09-28 22:35:57 -0500310 OkCodes: []int{204},
311 })
Ash Wilson72e4d2c2014-10-20 10:27:30 -0400312 res.Header = resp.HttpResponse.Header
Jon Perritt5db08922014-09-30 21:32:48 -0500313 res.Err = err
314 return res
Jon Perritt8c93a302014-09-28 22:35:57 -0500315}
316
Jon Perritte90aced2014-10-12 23:24:06 -0500317// GetOptsBuilder allows extensions to add additional parameters to the
318// Get request.
319type GetOptsBuilder interface {
Jon Perritt26780d52014-10-14 11:35:58 -0500320 ToObjectGetQuery() (string, error)
Jon Perritte90aced2014-10-12 23:24:06 -0500321}
322
Jon Perritt8c93a302014-09-28 22:35:57 -0500323// GetOpts is a structure that holds parameters for getting an object's metadata.
324type GetOpts struct {
325 Expires string `q:"expires"`
326 Signature string `q:"signature"`
327}
328
Jon Perritt26780d52014-10-14 11:35:58 -0500329// ToObjectGetQuery formats a GetOpts into a query string.
330func (opts GetOpts) ToObjectGetQuery() (string, error) {
Jon Perritte90aced2014-10-12 23:24:06 -0500331 q, err := gophercloud.BuildQueryString(opts)
332 if err != nil {
333 return "", err
334 }
335 return q.String(), nil
336}
337
Jon Perritt8c93a302014-09-28 22:35:57 -0500338// Get is a function that retrieves the metadata of an object. To extract just the custom
339// metadata, pass the GetResult response to the ExtractMetadata function.
Jon Perritte90aced2014-10-12 23:24:06 -0500340func Get(c *gophercloud.ServiceClient, containerName, objectName string, opts GetOptsBuilder) GetResult {
Jon Perritt5db08922014-09-30 21:32:48 -0500341 var res GetResult
Jon Perrittea4e3012014-10-09 22:03:19 -0500342 url := getURL(c, containerName, objectName)
Jon Perrittde47eac2014-09-30 15:34:17 -0500343
344 if opts != nil {
Jon Perritt26780d52014-10-14 11:35:58 -0500345 query, err := opts.ToObjectGetQuery()
Jon Perrittde47eac2014-09-30 15:34:17 -0500346 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500347 res.Err = err
348 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500349 }
Jon Perritte90aced2014-10-12 23:24:06 -0500350 url += query
Jon Perritt8c93a302014-09-28 22:35:57 -0500351 }
352
Jon Perritt8c93a302014-09-28 22:35:57 -0500353 resp, err := perigee.Request("HEAD", url, perigee.Options{
Ash Wilson77857dc2014-10-22 09:09:02 -0400354 MoreHeaders: c.AuthenticatedHeaders(),
Jon Perritt8c93a302014-09-28 22:35:57 -0500355 OkCodes: []int{200, 204},
356 })
Ash Wilson72e4d2c2014-10-20 10:27:30 -0400357 res.Header = resp.HttpResponse.Header
Jon Perritt5db08922014-09-30 21:32:48 -0500358 res.Err = err
Jon Perritt5db08922014-09-30 21:32:48 -0500359 return res
Jon Perritt8c93a302014-09-28 22:35:57 -0500360}
361
Jon Perritte90aced2014-10-12 23:24:06 -0500362// UpdateOptsBuilder allows extensions to add additional parameters to the
363// Update request.
364type UpdateOptsBuilder interface {
Jon Perritt04851d32014-10-14 02:07:13 -0500365 ToObjectUpdateMap() (map[string]string, error)
Jon Perritte90aced2014-10-12 23:24:06 -0500366}
367
Jon Perritt8c93a302014-09-28 22:35:57 -0500368// UpdateOpts is a structure that holds parameters for updating, creating, or deleting an
369// object's metadata.
370type UpdateOpts struct {
371 Metadata map[string]string
372 ContentDisposition string `h:"Content-Disposition"`
373 ContentEncoding string `h:"Content-Encoding"`
374 ContentType string `h:"Content-Type"`
375 DeleteAfter int `h:"X-Delete-After"`
376 DeleteAt int `h:"X-Delete-At"`
377 DetectContentType bool `h:"X-Detect-Content-Type"`
378}
379
Jon Perritt04851d32014-10-14 02:07:13 -0500380// ToObjectUpdateMap formats a UpdateOpts into a map of headers.
381func (opts UpdateOpts) ToObjectUpdateMap() (map[string]string, error) {
Jon Perritte90aced2014-10-12 23:24:06 -0500382 h, err := gophercloud.BuildHeaders(opts)
383 if err != nil {
384 return nil, err
385 }
386 for k, v := range opts.Metadata {
387 h["X-Object-Meta-"+k] = v
388 }
389 return h, nil
390}
391
Jon Perritt8c93a302014-09-28 22:35:57 -0500392// Update is a function that creates, updates, or deletes an object's metadata.
Jon Perritte90aced2014-10-12 23:24:06 -0500393func Update(c *gophercloud.ServiceClient, containerName, objectName string, opts UpdateOptsBuilder) UpdateResult {
Jon Perritt5db08922014-09-30 21:32:48 -0500394 var res UpdateResult
Ash Wilson77857dc2014-10-22 09:09:02 -0400395 h := c.AuthenticatedHeaders()
Jon Perritt8c93a302014-09-28 22:35:57 -0500396
Jon Perrittde47eac2014-09-30 15:34:17 -0500397 if opts != nil {
Jon Perritt04851d32014-10-14 02:07:13 -0500398 headers, err := opts.ToObjectUpdateMap()
Jon Perrittde47eac2014-09-30 15:34:17 -0500399 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500400 res.Err = err
401 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500402 }
Jon Perritt8c93a302014-09-28 22:35:57 -0500403
Jon Perrittde47eac2014-09-30 15:34:17 -0500404 for k, v := range headers {
405 h[k] = v
406 }
Jon Perritt8c93a302014-09-28 22:35:57 -0500407 }
408
Jon Perrittea4e3012014-10-09 22:03:19 -0500409 url := updateURL(c, containerName, objectName)
Jon Perritt5db08922014-09-30 21:32:48 -0500410 resp, err := perigee.Request("POST", url, perigee.Options{
Jon Perritt816d2a02014-03-11 20:49:46 -0500411 MoreHeaders: h,
Ash Wilsone47ea9e2014-09-10 16:03:44 -0400412 OkCodes: []int{202},
Jon Perritt816d2a02014-03-11 20:49:46 -0500413 })
Ash Wilson72e4d2c2014-10-20 10:27:30 -0400414 res.Header = resp.HttpResponse.Header
Jon Perritt5db08922014-09-30 21:32:48 -0500415 res.Err = err
416 return res
Jon Perritt816d2a02014-03-11 20:49:46 -0500417}