blob: 13d94f88cbe3eacc4ad51b33e09cd463a2205a07 [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 Wilson604320e2014-09-10 16:02:28 -0400112 h := c.Provider.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 var reqBody []byte
189
Jon Perrittea4e3012014-10-09 22:03:19 -0500190 url := createURL(c, containerName, objectName)
Ash Wilson604320e2014-09-10 16:02:28 -0400191 h := c.Provider.AuthenticatedHeaders()
Jon Perritt816d2a02014-03-11 20:49:46 -0500192
Jon Perrittde47eac2014-09-30 15:34:17 -0500193 if opts != nil {
Jon Perritte90aced2014-10-12 23:24:06 -0500194 headers, query, err := opts.ToObjectCreateParams()
Jon Perrittde47eac2014-09-30 15:34:17 -0500195 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500196 res.Err = err
197 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500198 }
Jon Perritt8c93a302014-09-28 22:35:57 -0500199
Jon Perrittde47eac2014-09-30 15:34:17 -0500200 for k, v := range headers {
201 h[k] = v
202 }
Jon Perritt816d2a02014-03-11 20:49:46 -0500203
Jon Perritte90aced2014-10-12 23:24:06 -0500204 url += query
Jon Perritt8c93a302014-09-28 22:35:57 -0500205 }
Jon Perritt816d2a02014-03-11 20:49:46 -0500206
Jon Perritt816d2a02014-03-11 20:49:46 -0500207 if content != nil {
Jon Perritt884e0312014-08-14 17:25:38 -0500208 reqBody = make([]byte, 0)
Ash Wilson604320e2014-09-10 16:02:28 -0400209 _, err := content.Read(reqBody)
Jon Perritt816d2a02014-03-11 20:49:46 -0500210 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500211 res.Err = err
212 return res
Jon Perritt816d2a02014-03-11 20:49:46 -0500213 }
214 }
215
Jon Perritt5db08922014-09-30 21:32:48 -0500216 resp, err := perigee.Request("PUT", url, perigee.Options{
Jon Perritt816d2a02014-03-11 20:49:46 -0500217 ReqBody: reqBody,
218 MoreHeaders: h,
Ash Wilsone47ea9e2014-09-10 16:03:44 -0400219 OkCodes: []int{201},
Jon Perritt816d2a02014-03-11 20:49:46 -0500220 })
Ash Wilson72e4d2c2014-10-20 10:27:30 -0400221 res.Header = resp.HttpResponse.Header
Jon Perritt5db08922014-09-30 21:32:48 -0500222 res.Err = err
223 return res
Jon Perritt816d2a02014-03-11 20:49:46 -0500224}
225
Jon Perritte90aced2014-10-12 23:24:06 -0500226// CopyOptsBuilder allows extensions to add additional parameters to the
227// Copy request.
228type CopyOptsBuilder interface {
Jon Perritt04851d32014-10-14 02:07:13 -0500229 ToObjectCopyMap() (map[string]string, error)
Jon Perritte90aced2014-10-12 23:24:06 -0500230}
231
232// CopyOpts is a structure that holds parameters for copying one object to
233// another.
Jon Perritt8c93a302014-09-28 22:35:57 -0500234type CopyOpts struct {
235 Metadata map[string]string
236 ContentDisposition string `h:"Content-Disposition"`
237 ContentEncoding string `h:"Content-Encoding"`
238 ContentType string `h:"Content-Type"`
239 Destination string `h:"Destination,required"`
240}
241
Jon Perritt04851d32014-10-14 02:07:13 -0500242// ToObjectCopyMap formats a CopyOpts into a map of headers.
243func (opts CopyOpts) ToObjectCopyMap() (map[string]string, error) {
Jon Perritte90aced2014-10-12 23:24:06 -0500244 if opts.Destination == "" {
245 return nil, fmt.Errorf("Required CopyOpts field 'Destination' not set.")
246 }
247 h, err := gophercloud.BuildHeaders(opts)
248 if err != nil {
249 return nil, err
250 }
251 for k, v := range opts.Metadata {
252 h["X-Object-Meta-"+k] = v
253 }
254 return h, nil
255}
256
Jon Perritt816d2a02014-03-11 20:49:46 -0500257// Copy is a function that copies one object to another.
Jon Perritte90aced2014-10-12 23:24:06 -0500258func Copy(c *gophercloud.ServiceClient, containerName, objectName string, opts CopyOptsBuilder) CopyResult {
Jon Perritt5db08922014-09-30 21:32:48 -0500259 var res CopyResult
Ash Wilson604320e2014-09-10 16:02:28 -0400260 h := c.Provider.AuthenticatedHeaders()
Jon Perritt816d2a02014-03-11 20:49:46 -0500261
Jon Perritt04851d32014-10-14 02:07:13 -0500262 headers, err := opts.ToObjectCopyMap()
Jon Perritt8c93a302014-09-28 22:35:57 -0500263 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500264 res.Err = err
265 return res
Jon Perritt816d2a02014-03-11 20:49:46 -0500266 }
Jon Perritte90aced2014-10-12 23:24:06 -0500267
Jon Perritt8c93a302014-09-28 22:35:57 -0500268 for k, v := range headers {
Jon Perritt816d2a02014-03-11 20:49:46 -0500269 h[k] = v
270 }
271
Jon Perrittea4e3012014-10-09 22:03:19 -0500272 url := copyURL(c, containerName, objectName)
Jon Perritt5db08922014-09-30 21:32:48 -0500273 resp, err := perigee.Request("COPY", url, perigee.Options{
Jon Perritt8c93a302014-09-28 22:35:57 -0500274 MoreHeaders: h,
275 OkCodes: []int{201},
276 })
Ash Wilson72e4d2c2014-10-20 10:27:30 -0400277 res.Header = resp.HttpResponse.Header
Jon Perritt5db08922014-09-30 21:32:48 -0500278 return res
Jon Perritt8c93a302014-09-28 22:35:57 -0500279}
280
Jon Perritte90aced2014-10-12 23:24:06 -0500281// DeleteOptsBuilder allows extensions to add additional parameters to the
282// Delete request.
283type DeleteOptsBuilder interface {
Jon Perritt26780d52014-10-14 11:35:58 -0500284 ToObjectDeleteQuery() (string, error)
Jon Perritte90aced2014-10-12 23:24:06 -0500285}
286
Jon Perritt8c93a302014-09-28 22:35:57 -0500287// DeleteOpts is a structure that holds parameters for deleting an object.
288type DeleteOpts struct {
289 MultipartManifest string `q:"multipart-manifest"`
290}
291
Jon Perritt26780d52014-10-14 11:35:58 -0500292// ToObjectDeleteQuery formats a DeleteOpts into a query string.
293func (opts DeleteOpts) ToObjectDeleteQuery() (string, error) {
Jon Perritte90aced2014-10-12 23:24:06 -0500294 q, err := gophercloud.BuildQueryString(opts)
295 if err != nil {
296 return "", err
297 }
298 return q.String(), nil
299}
300
Jon Perritt8c93a302014-09-28 22:35:57 -0500301// Delete is a function that deletes an object.
Jon Perritte90aced2014-10-12 23:24:06 -0500302func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts DeleteOptsBuilder) DeleteResult {
Jon Perritt5db08922014-09-30 21:32:48 -0500303 var res DeleteResult
Jon Perrittea4e3012014-10-09 22:03:19 -0500304 url := deleteURL(c, containerName, objectName)
Jon Perritt8c93a302014-09-28 22:35:57 -0500305
Jon Perrittde47eac2014-09-30 15:34:17 -0500306 if opts != nil {
Jon Perritt26780d52014-10-14 11:35:58 -0500307 query, err := opts.ToObjectDeleteQuery()
Jon Perrittde47eac2014-09-30 15:34:17 -0500308 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500309 res.Err = err
310 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500311 }
Jon Perritte90aced2014-10-12 23:24:06 -0500312 url += query
Jon Perritt8c93a302014-09-28 22:35:57 -0500313 }
314
Jon Perritt5db08922014-09-30 21:32:48 -0500315 resp, err := perigee.Request("DELETE", url, perigee.Options{
Jon Perrittde47eac2014-09-30 15:34:17 -0500316 MoreHeaders: c.Provider.AuthenticatedHeaders(),
Jon Perritt8c93a302014-09-28 22:35:57 -0500317 OkCodes: []int{204},
318 })
Ash Wilson72e4d2c2014-10-20 10:27:30 -0400319 res.Header = resp.HttpResponse.Header
Jon Perritt5db08922014-09-30 21:32:48 -0500320 res.Err = err
321 return res
Jon Perritt8c93a302014-09-28 22:35:57 -0500322}
323
Jon Perritte90aced2014-10-12 23:24:06 -0500324// GetOptsBuilder allows extensions to add additional parameters to the
325// Get request.
326type GetOptsBuilder interface {
Jon Perritt26780d52014-10-14 11:35:58 -0500327 ToObjectGetQuery() (string, error)
Jon Perritte90aced2014-10-12 23:24:06 -0500328}
329
Jon Perritt8c93a302014-09-28 22:35:57 -0500330// GetOpts is a structure that holds parameters for getting an object's metadata.
331type GetOpts struct {
332 Expires string `q:"expires"`
333 Signature string `q:"signature"`
334}
335
Jon Perritt26780d52014-10-14 11:35:58 -0500336// ToObjectGetQuery formats a GetOpts into a query string.
337func (opts GetOpts) ToObjectGetQuery() (string, error) {
Jon Perritte90aced2014-10-12 23:24:06 -0500338 q, err := gophercloud.BuildQueryString(opts)
339 if err != nil {
340 return "", err
341 }
342 return q.String(), nil
343}
344
Jon Perritt8c93a302014-09-28 22:35:57 -0500345// Get is a function that retrieves the metadata of an object. To extract just the custom
346// metadata, pass the GetResult response to the ExtractMetadata function.
Jon Perritte90aced2014-10-12 23:24:06 -0500347func Get(c *gophercloud.ServiceClient, containerName, objectName string, opts GetOptsBuilder) GetResult {
Jon Perritt5db08922014-09-30 21:32:48 -0500348 var res GetResult
Jon Perrittea4e3012014-10-09 22:03:19 -0500349 url := getURL(c, containerName, objectName)
Jon Perrittde47eac2014-09-30 15:34:17 -0500350
351 if opts != nil {
Jon Perritt26780d52014-10-14 11:35:58 -0500352 query, err := opts.ToObjectGetQuery()
Jon Perrittde47eac2014-09-30 15:34:17 -0500353 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500354 res.Err = err
355 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500356 }
Jon Perritte90aced2014-10-12 23:24:06 -0500357 url += query
Jon Perritt8c93a302014-09-28 22:35:57 -0500358 }
359
Jon Perritt8c93a302014-09-28 22:35:57 -0500360 resp, err := perigee.Request("HEAD", url, perigee.Options{
361 MoreHeaders: c.Provider.AuthenticatedHeaders(),
362 OkCodes: []int{200, 204},
363 })
Ash Wilson72e4d2c2014-10-20 10:27:30 -0400364 res.Header = resp.HttpResponse.Header
Jon Perritt5db08922014-09-30 21:32:48 -0500365 res.Err = err
Jon Perritt5db08922014-09-30 21:32:48 -0500366 return res
Jon Perritt8c93a302014-09-28 22:35:57 -0500367}
368
Jon Perritte90aced2014-10-12 23:24:06 -0500369// UpdateOptsBuilder allows extensions to add additional parameters to the
370// Update request.
371type UpdateOptsBuilder interface {
Jon Perritt04851d32014-10-14 02:07:13 -0500372 ToObjectUpdateMap() (map[string]string, error)
Jon Perritte90aced2014-10-12 23:24:06 -0500373}
374
Jon Perritt8c93a302014-09-28 22:35:57 -0500375// UpdateOpts is a structure that holds parameters for updating, creating, or deleting an
376// object's metadata.
377type UpdateOpts struct {
378 Metadata map[string]string
379 ContentDisposition string `h:"Content-Disposition"`
380 ContentEncoding string `h:"Content-Encoding"`
381 ContentType string `h:"Content-Type"`
382 DeleteAfter int `h:"X-Delete-After"`
383 DeleteAt int `h:"X-Delete-At"`
384 DetectContentType bool `h:"X-Detect-Content-Type"`
385}
386
Jon Perritt04851d32014-10-14 02:07:13 -0500387// ToObjectUpdateMap formats a UpdateOpts into a map of headers.
388func (opts UpdateOpts) ToObjectUpdateMap() (map[string]string, error) {
Jon Perritte90aced2014-10-12 23:24:06 -0500389 h, err := gophercloud.BuildHeaders(opts)
390 if err != nil {
391 return nil, err
392 }
393 for k, v := range opts.Metadata {
394 h["X-Object-Meta-"+k] = v
395 }
396 return h, nil
397}
398
Jon Perritt8c93a302014-09-28 22:35:57 -0500399// Update is a function that creates, updates, or deletes an object's metadata.
Jon Perritte90aced2014-10-12 23:24:06 -0500400func Update(c *gophercloud.ServiceClient, containerName, objectName string, opts UpdateOptsBuilder) UpdateResult {
Jon Perritt5db08922014-09-30 21:32:48 -0500401 var res UpdateResult
Jon Perritt8c93a302014-09-28 22:35:57 -0500402 h := c.Provider.AuthenticatedHeaders()
403
Jon Perrittde47eac2014-09-30 15:34:17 -0500404 if opts != nil {
Jon Perritt04851d32014-10-14 02:07:13 -0500405 headers, err := opts.ToObjectUpdateMap()
Jon Perrittde47eac2014-09-30 15:34:17 -0500406 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500407 res.Err = err
408 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500409 }
Jon Perritt8c93a302014-09-28 22:35:57 -0500410
Jon Perrittde47eac2014-09-30 15:34:17 -0500411 for k, v := range headers {
412 h[k] = v
413 }
Jon Perritt8c93a302014-09-28 22:35:57 -0500414 }
415
Jon Perrittea4e3012014-10-09 22:03:19 -0500416 url := updateURL(c, containerName, objectName)
Jon Perritt5db08922014-09-30 21:32:48 -0500417 resp, err := perigee.Request("POST", url, perigee.Options{
Jon Perritt816d2a02014-03-11 20:49:46 -0500418 MoreHeaders: h,
Ash Wilsone47ea9e2014-09-10 16:03:44 -0400419 OkCodes: []int{202},
Jon Perritt816d2a02014-03-11 20:49:46 -0500420 })
Ash Wilson72e4d2c2014-10-20 10:27:30 -0400421 res.Header = resp.HttpResponse.Header
Jon Perritt5db08922014-09-30 21:32:48 -0500422 res.Err = err
423 return res
Jon Perritt816d2a02014-03-11 20:49:46 -0500424}