blob: 9778de3be6d6a0102d3f945511c9ddbe2fa55223 [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 Perritte90aced2014-10-12 23:24:06 -050013// ListOptsBuilder allows extensions to add additional parameters to the List
14// request.
15type ListOptsBuilder interface {
16 ToObjectListParams() (bool, string, error)
17}
18
Jon Perritt8c93a302014-09-28 22:35:57 -050019// ListOpts is a structure that holds parameters for listing objects.
20type ListOpts struct {
21 Full bool
Jon Perritt04851d32014-10-14 02:07:13 -050022 Limit int `q:"limit"`
23 Marker string `q:"marker"`
24 EndMarker string `q:"end_marker"`
25 Format string `q:"format"`
26 Prefix string `q:"prefix"`
27 Delimiter string `q:"delimiter"`
28 Path string `q:"path"`
Ash Wilsonca6f7562014-09-16 15:43:54 -040029}
30
Jon Perritte90aced2014-10-12 23:24:06 -050031// ToObjectListParams formats a ListOpts into a query string and boolean
32// representing whether to list complete information for each object.
33func (opts ListOpts) ToObjectListParams() (bool, string, error) {
34 q, err := gophercloud.BuildQueryString(opts)
35 if err != nil {
36 return false, "", err
37 }
38 return opts.Full, q.String(), nil
39}
40
Jon Perritt816d2a02014-03-11 20:49:46 -050041// List is a function that retrieves all objects in a container. It also returns the details
42// for the container. To extract only the object information or names, pass the ListResult
Jon Perritteb575642014-04-24 15:16:31 -050043// response to the ExtractInfo or ExtractNames function, respectively.
Jon Perritte90aced2014-10-12 23:24:06 -050044func List(c *gophercloud.ServiceClient, containerName string, opts ListOptsBuilder) pagination.Pager {
45 headers := map[string]string{"Accept": "text/plain", "Content-Type": "text/plain"}
Jon Perritt816d2a02014-03-11 20:49:46 -050046
Jon Perrittea4e3012014-10-09 22:03:19 -050047 url := listURL(c, containerName)
Jon Perrittde47eac2014-09-30 15:34:17 -050048 if opts != nil {
Jon Perritte90aced2014-10-12 23:24:06 -050049 full, query, err := opts.ToObjectListParams()
Jon Perrittde47eac2014-09-30 15:34:17 -050050 if err != nil {
Jon Perrittde47eac2014-09-30 15:34:17 -050051 return pagination.Pager{Err: err}
52 }
Jon Perritte90aced2014-10-12 23:24:06 -050053 url += query
Jon Perritt816d2a02014-03-11 20:49:46 -050054
Jon Perritte90aced2014-10-12 23:24:06 -050055 if full {
56 headers = map[string]string{"Accept": "application/json", "Content-Type": "application/json"}
Jon Perrittde47eac2014-09-30 15:34:17 -050057 }
Ash Wilsonca6f7562014-09-16 15:43:54 -040058 }
59
Ash Wilsonb8b16f82014-10-20 10:19:49 -040060 createPage := func(r pagination.PageResult) pagination.Page {
61 p := ObjectPage{pagination.MarkerPageBase{PageResult: r}}
Ash Wilsonca6f7562014-09-16 15:43:54 -040062 p.MarkerPageBase.Owner = p
63 return p
Jon Perritt816d2a02014-03-11 20:49:46 -050064 }
65
Ash Wilsonca6f7562014-09-16 15:43:54 -040066 pager := pagination.NewPager(c, url, createPage)
67 pager.Headers = headers
68 return pager
Jon Perritt816d2a02014-03-11 20:49:46 -050069}
70
Jon Perritte90aced2014-10-12 23:24:06 -050071// DownloadOptsBuilder allows extensions to add additional parameters to the
72// Download request.
73type DownloadOptsBuilder interface {
74 ToObjectDownloadParams() (map[string]string, string, error)
75}
76
Jon Perritt8c93a302014-09-28 22:35:57 -050077// DownloadOpts is a structure that holds parameters for downloading an object.
78type DownloadOpts struct {
79 IfMatch string `h:"If-Match"`
80 IfModifiedSince time.Time `h:"If-Modified-Since"`
81 IfNoneMatch string `h:"If-None-Match"`
82 IfUnmodifiedSince time.Time `h:"If-Unmodified-Since"`
83 Range string `h:"Range"`
84 Expires string `q:"expires"`
85 MultipartManifest string `q:"multipart-manifest"`
86 Signature string `q:"signature"`
87}
88
Jon Perritte90aced2014-10-12 23:24:06 -050089// ToObjectDownloadParams formats a DownloadOpts into a query string and map of
90// headers.
91func (opts ListOpts) ToObjectDownloadParams() (map[string]string, string, error) {
92 q, err := gophercloud.BuildQueryString(opts)
93 if err != nil {
94 return nil, "", err
95 }
96 h, err := gophercloud.BuildHeaders(opts)
97 if err != nil {
98 return nil, q.String(), err
99 }
100 return h, q.String(), nil
101}
102
Jon Perritt816d2a02014-03-11 20:49:46 -0500103// Download is a function that retrieves the content and metadata for an object.
Jon Perritte90aced2014-10-12 23:24:06 -0500104// To extract just the content, pass the DownloadResult response to the
105// ExtractContent function.
106func Download(c *gophercloud.ServiceClient, containerName, objectName string, opts DownloadOptsBuilder) DownloadResult {
Jon Perritt5db08922014-09-30 21:32:48 -0500107 var res DownloadResult
Jon Perritt8c93a302014-09-28 22:35:57 -0500108
Jon Perrittea4e3012014-10-09 22:03:19 -0500109 url := downloadURL(c, containerName, objectName)
Ash Wilson77857dc2014-10-22 09:09:02 -0400110 h := c.AuthenticatedHeaders()
Jon Perritt816d2a02014-03-11 20:49:46 -0500111
Jon Perrittde47eac2014-09-30 15:34:17 -0500112 if opts != nil {
Jon Perritte90aced2014-10-12 23:24:06 -0500113 headers, query, err := opts.ToObjectDownloadParams()
Jon Perrittde47eac2014-09-30 15:34:17 -0500114 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500115 res.Err = err
116 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500117 }
118
119 for k, v := range headers {
120 h[k] = v
121 }
122
Jon Perritte90aced2014-10-12 23:24:06 -0500123 url += query
Jon Perritt8c93a302014-09-28 22:35:57 -0500124 }
125
Jon Perritt816d2a02014-03-11 20:49:46 -0500126 resp, err := perigee.Request("GET", url, perigee.Options{
Jon Perritt816d2a02014-03-11 20:49:46 -0500127 MoreHeaders: h,
Ash Wilsone47ea9e2014-09-10 16:03:44 -0400128 OkCodes: []int{200},
Jon Perritt816d2a02014-03-11 20:49:46 -0500129 })
Jamie Hannaford2e784862014-10-27 10:40:27 +0100130
131 res.Body = resp.HttpResponse.Body
Jon Perritt5db08922014-09-30 21:32:48 -0500132 res.Err = err
Ash Wilson72e4d2c2014-10-20 10:27:30 -0400133 res.Header = resp.HttpResponse.Header
Jamie Hannaford2e784862014-10-27 10:40:27 +0100134
Jon Perritt5db08922014-09-30 21:32:48 -0500135 return res
Jon Perritt8c93a302014-09-28 22:35:57 -0500136}
137
Jon Perritte90aced2014-10-12 23:24:06 -0500138// CreateOptsBuilder allows extensions to add additional parameters to the
139// Create request.
140type CreateOptsBuilder interface {
141 ToObjectCreateParams() (map[string]string, string, error)
142}
143
Jon Perritt8c93a302014-09-28 22:35:57 -0500144// CreateOpts is a structure that holds parameters for creating an object.
145type CreateOpts struct {
146 Metadata map[string]string
147 ContentDisposition string `h:"Content-Disposition"`
148 ContentEncoding string `h:"Content-Encoding"`
149 ContentLength int `h:"Content-Length"`
150 ContentType string `h:"Content-Type"`
151 CopyFrom string `h:"X-Copy-From"`
152 DeleteAfter int `h:"X-Delete-After"`
153 DeleteAt int `h:"X-Delete-At"`
154 DetectContentType string `h:"X-Detect-Content-Type"`
155 ETag string `h:"ETag"`
156 IfNoneMatch string `h:"If-None-Match"`
157 ObjectManifest string `h:"X-Object-Manifest"`
158 TransferEncoding string `h:"Transfer-Encoding"`
159 Expires string `q:"expires"`
160 MultipartManifest string `q:"multiple-manifest"`
161 Signature string `q:"signature"`
Jon Perritt816d2a02014-03-11 20:49:46 -0500162}
163
Jon Perritte90aced2014-10-12 23:24:06 -0500164// ToObjectCreateParams formats a CreateOpts into a query string and map of
165// headers.
166func (opts CreateOpts) ToObjectCreateParams() (map[string]string, string, error) {
167 q, err := gophercloud.BuildQueryString(opts)
168 if err != nil {
169 return nil, "", err
170 }
171 h, err := gophercloud.BuildHeaders(opts)
172 if err != nil {
173 return nil, q.String(), err
174 }
175
176 for k, v := range opts.Metadata {
177 h["X-Object-Meta-"+k] = v
178 }
179
180 return h, q.String(), nil
181}
182
Jon Perritt816d2a02014-03-11 20:49:46 -0500183// Create is a function that creates a new object or replaces an existing object.
Jon Perritte90aced2014-10-12 23:24:06 -0500184func Create(c *gophercloud.ServiceClient, containerName, objectName string, content io.Reader, opts CreateOptsBuilder) CreateResult {
Jon Perritt5db08922014-09-30 21:32:48 -0500185 var res CreateResult
Jon Perritt816d2a02014-03-11 20:49:46 -0500186
Jon Perrittea4e3012014-10-09 22:03:19 -0500187 url := createURL(c, containerName, objectName)
Ash Wilson77857dc2014-10-22 09:09:02 -0400188 h := c.AuthenticatedHeaders()
Jon Perritt816d2a02014-03-11 20:49:46 -0500189
Jon Perrittde47eac2014-09-30 15:34:17 -0500190 if opts != nil {
Jon Perritte90aced2014-10-12 23:24:06 -0500191 headers, query, err := opts.ToObjectCreateParams()
Jon Perrittde47eac2014-09-30 15:34:17 -0500192 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500193 res.Err = err
194 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500195 }
Jon Perritt8c93a302014-09-28 22:35:57 -0500196
Jon Perrittde47eac2014-09-30 15:34:17 -0500197 for k, v := range headers {
198 h[k] = v
199 }
Jon Perritt816d2a02014-03-11 20:49:46 -0500200
Jon Perritte90aced2014-10-12 23:24:06 -0500201 url += query
Jon Perritt8c93a302014-09-28 22:35:57 -0500202 }
Jon Perritt816d2a02014-03-11 20:49:46 -0500203
Jon Perritta77ba0d2014-10-17 01:15:29 -0500204 contentType := h["Content-Type"]
Jon Perritt816d2a02014-03-11 20:49:46 -0500205
Jon Perritt5db08922014-09-30 21:32:48 -0500206 resp, err := perigee.Request("PUT", url, perigee.Options{
Jon Perritta77ba0d2014-10-17 01:15:29 -0500207 ContentType: contentType,
208 ReqBody: content,
Jon Perritt816d2a02014-03-11 20:49:46 -0500209 MoreHeaders: h,
Jon Perritta77ba0d2014-10-17 01:15:29 -0500210 OkCodes: []int{201, 202},
Jon Perritt816d2a02014-03-11 20:49:46 -0500211 })
Ash Wilson72e4d2c2014-10-20 10:27:30 -0400212 res.Header = resp.HttpResponse.Header
Jon Perritt5db08922014-09-30 21:32:48 -0500213 res.Err = err
214 return res
Jon Perritt816d2a02014-03-11 20:49:46 -0500215}
216
Jon Perritte90aced2014-10-12 23:24:06 -0500217// CopyOptsBuilder allows extensions to add additional parameters to the
218// Copy request.
219type CopyOptsBuilder interface {
Jon Perritt04851d32014-10-14 02:07:13 -0500220 ToObjectCopyMap() (map[string]string, error)
Jon Perritte90aced2014-10-12 23:24:06 -0500221}
222
223// CopyOpts is a structure that holds parameters for copying one object to
224// another.
Jon Perritt8c93a302014-09-28 22:35:57 -0500225type CopyOpts struct {
226 Metadata map[string]string
227 ContentDisposition string `h:"Content-Disposition"`
228 ContentEncoding string `h:"Content-Encoding"`
229 ContentType string `h:"Content-Type"`
230 Destination string `h:"Destination,required"`
231}
232
Jon Perritt04851d32014-10-14 02:07:13 -0500233// ToObjectCopyMap formats a CopyOpts into a map of headers.
234func (opts CopyOpts) ToObjectCopyMap() (map[string]string, error) {
Jon Perritte90aced2014-10-12 23:24:06 -0500235 if opts.Destination == "" {
236 return nil, fmt.Errorf("Required CopyOpts field 'Destination' not set.")
237 }
238 h, err := gophercloud.BuildHeaders(opts)
239 if err != nil {
240 return nil, err
241 }
242 for k, v := range opts.Metadata {
243 h["X-Object-Meta-"+k] = v
244 }
245 return h, nil
246}
247
Jon Perritt816d2a02014-03-11 20:49:46 -0500248// Copy is a function that copies one object to another.
Jon Perritte90aced2014-10-12 23:24:06 -0500249func Copy(c *gophercloud.ServiceClient, containerName, objectName string, opts CopyOptsBuilder) CopyResult {
Jon Perritt5db08922014-09-30 21:32:48 -0500250 var res CopyResult
Ash Wilson77857dc2014-10-22 09:09:02 -0400251 h := c.AuthenticatedHeaders()
Jon Perritt816d2a02014-03-11 20:49:46 -0500252
Jon Perritt04851d32014-10-14 02:07:13 -0500253 headers, err := opts.ToObjectCopyMap()
Jon Perritt8c93a302014-09-28 22:35:57 -0500254 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500255 res.Err = err
256 return res
Jon Perritt816d2a02014-03-11 20:49:46 -0500257 }
Jon Perritte90aced2014-10-12 23:24:06 -0500258
Jon Perritt8c93a302014-09-28 22:35:57 -0500259 for k, v := range headers {
Jon Perritt816d2a02014-03-11 20:49:46 -0500260 h[k] = v
261 }
262
Jon Perrittea4e3012014-10-09 22:03:19 -0500263 url := copyURL(c, containerName, objectName)
Jon Perritt5db08922014-09-30 21:32:48 -0500264 resp, err := perigee.Request("COPY", url, perigee.Options{
Jon Perritt8c93a302014-09-28 22:35:57 -0500265 MoreHeaders: h,
266 OkCodes: []int{201},
267 })
Ash Wilson72e4d2c2014-10-20 10:27:30 -0400268 res.Header = resp.HttpResponse.Header
jrperrittf7a8e282014-10-28 10:00:48 -0500269 res.Err = err
Jon Perritt5db08922014-09-30 21:32:48 -0500270 return res
Jon Perritt8c93a302014-09-28 22:35:57 -0500271}
272
Jon Perritte90aced2014-10-12 23:24:06 -0500273// DeleteOptsBuilder allows extensions to add additional parameters to the
274// Delete request.
275type DeleteOptsBuilder interface {
Jon Perritt26780d52014-10-14 11:35:58 -0500276 ToObjectDeleteQuery() (string, error)
Jon Perritte90aced2014-10-12 23:24:06 -0500277}
278
Jon Perritt8c93a302014-09-28 22:35:57 -0500279// DeleteOpts is a structure that holds parameters for deleting an object.
280type DeleteOpts struct {
281 MultipartManifest string `q:"multipart-manifest"`
282}
283
Jon Perritt26780d52014-10-14 11:35:58 -0500284// ToObjectDeleteQuery formats a DeleteOpts into a query string.
285func (opts DeleteOpts) ToObjectDeleteQuery() (string, error) {
Jon Perritte90aced2014-10-12 23:24:06 -0500286 q, err := gophercloud.BuildQueryString(opts)
287 if err != nil {
288 return "", err
289 }
290 return q.String(), nil
291}
292
Jon Perritt8c93a302014-09-28 22:35:57 -0500293// Delete is a function that deletes an object.
Jon Perritte90aced2014-10-12 23:24:06 -0500294func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts DeleteOptsBuilder) DeleteResult {
Jon Perritt5db08922014-09-30 21:32:48 -0500295 var res DeleteResult
Jon Perrittea4e3012014-10-09 22:03:19 -0500296 url := deleteURL(c, containerName, objectName)
Jon Perritt8c93a302014-09-28 22:35:57 -0500297
Jon Perrittde47eac2014-09-30 15:34:17 -0500298 if opts != nil {
Jon Perritt26780d52014-10-14 11:35:58 -0500299 query, err := opts.ToObjectDeleteQuery()
Jon Perrittde47eac2014-09-30 15:34:17 -0500300 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500301 res.Err = err
302 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500303 }
Jon Perritte90aced2014-10-12 23:24:06 -0500304 url += query
Jon Perritt8c93a302014-09-28 22:35:57 -0500305 }
306
Jon Perritt10a7ec12014-10-27 11:29:33 -0500307 resp, err := perigee.Request("DELETE", url, perigee.Options{
Ash Wilson77857dc2014-10-22 09:09:02 -0400308 MoreHeaders: c.AuthenticatedHeaders(),
Jon Perritt8c93a302014-09-28 22:35:57 -0500309 OkCodes: []int{204},
310 })
Jon Perritt10a7ec12014-10-27 11:29:33 -0500311 res.Header = resp.HttpResponse.Header
312 res.Err = err
Jon Perritt5db08922014-09-30 21:32:48 -0500313 return res
Jon Perritt8c93a302014-09-28 22:35:57 -0500314}
315
Jon Perritte90aced2014-10-12 23:24:06 -0500316// GetOptsBuilder allows extensions to add additional parameters to the
317// Get request.
318type GetOptsBuilder interface {
Jon Perritt26780d52014-10-14 11:35:58 -0500319 ToObjectGetQuery() (string, error)
Jon Perritte90aced2014-10-12 23:24:06 -0500320}
321
Jon Perritt8c93a302014-09-28 22:35:57 -0500322// GetOpts is a structure that holds parameters for getting an object's metadata.
323type GetOpts struct {
324 Expires string `q:"expires"`
325 Signature string `q:"signature"`
326}
327
Jon Perritt26780d52014-10-14 11:35:58 -0500328// ToObjectGetQuery formats a GetOpts into a query string.
329func (opts GetOpts) ToObjectGetQuery() (string, error) {
Jon Perritte90aced2014-10-12 23:24:06 -0500330 q, err := gophercloud.BuildQueryString(opts)
331 if err != nil {
332 return "", err
333 }
334 return q.String(), nil
335}
336
Jon Perritt8c93a302014-09-28 22:35:57 -0500337// Get is a function that retrieves the metadata of an object. To extract just the custom
338// metadata, pass the GetResult response to the ExtractMetadata function.
Jon Perritte90aced2014-10-12 23:24:06 -0500339func Get(c *gophercloud.ServiceClient, containerName, objectName string, opts GetOptsBuilder) GetResult {
Jon Perritt5db08922014-09-30 21:32:48 -0500340 var res GetResult
Jon Perrittea4e3012014-10-09 22:03:19 -0500341 url := getURL(c, containerName, objectName)
Jon Perrittde47eac2014-09-30 15:34:17 -0500342
343 if opts != nil {
Jon Perritt26780d52014-10-14 11:35:58 -0500344 query, err := opts.ToObjectGetQuery()
Jon Perrittde47eac2014-09-30 15:34:17 -0500345 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500346 res.Err = err
347 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500348 }
Jon Perritte90aced2014-10-12 23:24:06 -0500349 url += query
Jon Perritt8c93a302014-09-28 22:35:57 -0500350 }
351
Jon Perritt8c93a302014-09-28 22:35:57 -0500352 resp, err := perigee.Request("HEAD", url, perigee.Options{
Ash Wilson77857dc2014-10-22 09:09:02 -0400353 MoreHeaders: c.AuthenticatedHeaders(),
Jon Perritt8c93a302014-09-28 22:35:57 -0500354 OkCodes: []int{200, 204},
355 })
Ash Wilson72e4d2c2014-10-20 10:27:30 -0400356 res.Header = resp.HttpResponse.Header
Jon Perritt5db08922014-09-30 21:32:48 -0500357 res.Err = err
Jon Perritt5db08922014-09-30 21:32:48 -0500358 return res
Jon Perritt8c93a302014-09-28 22:35:57 -0500359}
360
Jon Perritte90aced2014-10-12 23:24:06 -0500361// UpdateOptsBuilder allows extensions to add additional parameters to the
362// Update request.
363type UpdateOptsBuilder interface {
Jon Perritt04851d32014-10-14 02:07:13 -0500364 ToObjectUpdateMap() (map[string]string, error)
Jon Perritte90aced2014-10-12 23:24:06 -0500365}
366
Jon Perritt8c93a302014-09-28 22:35:57 -0500367// UpdateOpts is a structure that holds parameters for updating, creating, or deleting an
368// object's metadata.
369type UpdateOpts struct {
370 Metadata map[string]string
371 ContentDisposition string `h:"Content-Disposition"`
372 ContentEncoding string `h:"Content-Encoding"`
373 ContentType string `h:"Content-Type"`
374 DeleteAfter int `h:"X-Delete-After"`
375 DeleteAt int `h:"X-Delete-At"`
376 DetectContentType bool `h:"X-Detect-Content-Type"`
377}
378
Jon Perritt04851d32014-10-14 02:07:13 -0500379// ToObjectUpdateMap formats a UpdateOpts into a map of headers.
380func (opts UpdateOpts) ToObjectUpdateMap() (map[string]string, error) {
Jon Perritte90aced2014-10-12 23:24:06 -0500381 h, err := gophercloud.BuildHeaders(opts)
382 if err != nil {
383 return nil, err
384 }
385 for k, v := range opts.Metadata {
386 h["X-Object-Meta-"+k] = v
387 }
388 return h, nil
389}
390
Jon Perritt8c93a302014-09-28 22:35:57 -0500391// Update is a function that creates, updates, or deletes an object's metadata.
Jon Perritte90aced2014-10-12 23:24:06 -0500392func Update(c *gophercloud.ServiceClient, containerName, objectName string, opts UpdateOptsBuilder) UpdateResult {
Jon Perritt5db08922014-09-30 21:32:48 -0500393 var res UpdateResult
Ash Wilson77857dc2014-10-22 09:09:02 -0400394 h := c.AuthenticatedHeaders()
Jon Perritt8c93a302014-09-28 22:35:57 -0500395
Jon Perrittde47eac2014-09-30 15:34:17 -0500396 if opts != nil {
Jon Perritt04851d32014-10-14 02:07:13 -0500397 headers, err := opts.ToObjectUpdateMap()
Jon Perrittde47eac2014-09-30 15:34:17 -0500398 if err != nil {
Jon Perritt5db08922014-09-30 21:32:48 -0500399 res.Err = err
400 return res
Jon Perrittde47eac2014-09-30 15:34:17 -0500401 }
Jon Perritt8c93a302014-09-28 22:35:57 -0500402
Jon Perrittde47eac2014-09-30 15:34:17 -0500403 for k, v := range headers {
404 h[k] = v
405 }
Jon Perritt8c93a302014-09-28 22:35:57 -0500406 }
407
Jon Perrittea4e3012014-10-09 22:03:19 -0500408 url := updateURL(c, containerName, objectName)
Jon Perritt5db08922014-09-30 21:32:48 -0500409 resp, err := perigee.Request("POST", url, perigee.Options{
Jon Perritt816d2a02014-03-11 20:49:46 -0500410 MoreHeaders: h,
Ash Wilsone47ea9e2014-09-10 16:03:44 -0400411 OkCodes: []int{202},
Jon Perritt816d2a02014-03-11 20:49:46 -0500412 })
Ash Wilson72e4d2c2014-10-20 10:27:30 -0400413 res.Header = resp.HttpResponse.Header
Jon Perritt5db08922014-09-30 21:32:48 -0500414 res.Err = err
415 return res
Jon Perritt816d2a02014-03-11 20:49:46 -0500416}