use generic parameter building functions; pagination in unit tests
diff --git a/openstack/storage/v1/objects/requests.go b/openstack/storage/v1/objects/requests.go
index 7b00127..363843c 100644
--- a/openstack/storage/v1/objects/requests.go
+++ b/openstack/storage/v1/objects/requests.go
@@ -2,97 +2,132 @@
import (
"fmt"
- "net/http"
+ "io"
+ "time"
"github.com/racker/perigee"
"github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/utils"
"github.com/rackspace/gophercloud/pagination"
)
-// ListResult is a single page of objects that is returned from a call to the List function.
-type ListResult struct {
- pagination.MarkerPageBase
+// ListOpts is a structure that holds parameters for listing objects.
+type ListOpts struct {
+ Full bool
+ Limit int `q:"limit"`
+ Marker string `q:"marker"`
+ EndMarker string `q:"end_marker"`
+ Format string `q:"format"`
+ Prefix string `q:"prefix"`
+ Delimiter [1]byte `q:"delimiter"`
+ Path string `q:"path"`
}
-// IsEmpty returns true if a ListResult contains no object names.
-func (r ListResult) IsEmpty() (bool, error) {
- names, err := ExtractNames(r)
- if err != nil {
- return true, err
- }
- return len(names) == 0, nil
-}
-
-// LastMarker returns the last object name in a ListResult.
-func (r ListResult) LastMarker() (string, error) {
- names, err := ExtractNames(r)
- if err != nil {
- return "", err
- }
- if len(names) == 0 {
- return "", nil
- }
- return names[len(names)-1], nil
-}
-
-// DownloadResult is a *http.Response that is returned from a call to the Download function.
-type DownloadResult *http.Response
-
-// GetResult is a *http.Response that is returned from a call to the Get function.
-type GetResult *http.Response
-
// List is a function that retrieves all objects in a container. It also returns the details
// for the container. To extract only the object information or names, pass the ListResult
// response to the ExtractInfo or ExtractNames function, respectively.
-func List(c *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
+func List(c *gophercloud.ServiceClient, containerName string, opts ListOpts) pagination.Pager {
var headers map[string]string
- query := utils.BuildQuery(opts.Params)
+ query, err := gophercloud.BuildQueryString(opts)
+ if err != nil {
+ fmt.Printf("Error building query string: %v", err)
+ return pagination.Pager{Err: err}
+ }
if !opts.Full {
- headers = map[string]string{"Content-Type": "text/plain"}
+ headers = map[string]string{"Accept": "text/plain"}
}
createPage := func(r pagination.LastHTTPResponse) pagination.Page {
- p := ListResult{pagination.MarkerPageBase{LastHTTPResponse: r}}
+ p := ObjectPage{pagination.MarkerPageBase{LastHTTPResponse: r}}
p.MarkerPageBase.Owner = p
return p
}
- url := containerURL(c, opts.Container) + query
+ url := containerURL(c, containerName) + query
pager := pagination.NewPager(c, url, createPage)
pager.Headers = headers
return pager
}
+// DownloadOpts is a structure that holds parameters for downloading an object.
+type DownloadOpts struct {
+ IfMatch string `h:"If-Match"`
+ IfModifiedSince time.Time `h:"If-Modified-Since"`
+ IfNoneMatch string `h:"If-None-Match"`
+ IfUnmodifiedSince time.Time `h:"If-Unmodified-Since"`
+ Range string `h:"Range"`
+ Expires string `q:"expires"`
+ MultipartManifest string `q:"multipart-manifest"`
+ Signature string `q:"signature"`
+}
+
// Download is a function that retrieves the content and metadata for an object.
// To extract just the content, pass the DownloadResult response to the ExtractContent
// function.
-func Download(c *gophercloud.ServiceClient, opts DownloadOpts) (DownloadResult, error) {
+func Download(c *gophercloud.ServiceClient, containerName, objectName string, opts DownloadOpts) DownloadResult {
+ var dr DownloadResult
+
h := c.Provider.AuthenticatedHeaders()
- for k, v := range opts.Headers {
+ headers, err := gophercloud.BuildHeaders(opts)
+ if err != nil {
+ dr.Err = err
+ return dr
+ }
+
+ for k, v := range headers {
h[k] = v
}
- query := utils.BuildQuery(opts.Params)
+ query, err := gophercloud.BuildQueryString(opts)
+ if err != nil {
+ dr.Err = err
+ return dr
+ }
- url := objectURL(c, opts.Container, opts.Name) + query
+ url := objectURL(c, containerName, objectName) + query
resp, err := perigee.Request("GET", url, perigee.Options{
MoreHeaders: h,
OkCodes: []int{200},
})
- return &resp.HttpResponse, err
+ dr.Err = err
+ dr.Resp = &resp.HttpResponse
+ return dr
+}
+
+// CreateOpts is a structure that holds parameters for creating an object.
+type CreateOpts struct {
+ Metadata map[string]string
+ ContentDisposition string `h:"Content-Disposition"`
+ ContentEncoding string `h:"Content-Encoding"`
+ ContentLength int `h:"Content-Length"`
+ ContentType string `h:"Content-Type"`
+ CopyFrom string `h:"X-Copy-From"`
+ DeleteAfter int `h:"X-Delete-After"`
+ DeleteAt int `h:"X-Delete-At"`
+ DetectContentType string `h:"X-Detect-Content-Type"`
+ ETag string `h:"ETag"`
+ IfNoneMatch string `h:"If-None-Match"`
+ ObjectManifest string `h:"X-Object-Manifest"`
+ TransferEncoding string `h:"Transfer-Encoding"`
+ Expires string `q:"expires"`
+ MultipartManifest string `q:"multiple-manifest"`
+ Signature string `q:"signature"`
}
// Create is a function that creates a new object or replaces an existing object.
-func Create(c *gophercloud.ServiceClient, opts CreateOpts) error {
+func Create(c *gophercloud.ServiceClient, containerName, objectName string, content io.Reader, opts CreateOpts) error {
var reqBody []byte
h := c.Provider.AuthenticatedHeaders()
- for k, v := range opts.Headers {
+ headers, err := gophercloud.BuildHeaders(opts)
+ if err != nil {
+ return nil
+ }
+
+ for k, v := range headers {
h[k] = v
}
@@ -100,9 +135,11 @@
h["X-Object-Meta-"+k] = v
}
- query := utils.BuildQuery(opts.Params)
+ query, err := gophercloud.BuildQueryString(opts)
+ if err != nil {
+ return err
+ }
- content := opts.Content
if content != nil {
reqBody = make([]byte, 0)
_, err := content.Read(reqBody)
@@ -111,8 +148,8 @@
}
}
- url := objectURL(c, opts.Container, opts.Name) + query
- _, err := perigee.Request("PUT", url, perigee.Options{
+ url := objectURL(c, containerName, objectName) + query
+ _, err = perigee.Request("PUT", url, perigee.Options{
ReqBody: reqBody,
MoreHeaders: h,
OkCodes: []int{201},
@@ -120,56 +157,24 @@
return err
}
+// CopyOpts is a structure that holds parameters for copying one object to another.
+type CopyOpts struct {
+ Metadata map[string]string
+ ContentDisposition string `h:"Content-Disposition"`
+ ContentEncoding string `h:"Content-Encoding"`
+ ContentType string `h:"Content-Type"`
+ Destination string `h:"Destination,required"`
+}
+
// Copy is a function that copies one object to another.
-func Copy(c *gophercloud.ServiceClient, opts CopyOpts) error {
+func Copy(c *gophercloud.ServiceClient, containerName, objectName string, opts CopyOpts) error {
h := c.Provider.AuthenticatedHeaders()
- for k, v := range opts.Metadata {
- h["X-Object-Meta-"+k] = v
+ headers, err := gophercloud.BuildHeaders(opts)
+ if err != nil {
+ return err
}
-
- h["Destination"] = fmt.Sprintf("/%s/%s", opts.NewContainer, opts.NewName)
-
- url := objectURL(c, opts.Container, opts.Name)
- _, err := perigee.Request("COPY", url, perigee.Options{
- MoreHeaders: h,
- OkCodes: []int{201},
- })
- return err
-}
-
-// Delete is a function that deletes an object.
-func Delete(c *gophercloud.ServiceClient, opts DeleteOpts) error {
- h := c.Provider.AuthenticatedHeaders()
-
- query := utils.BuildQuery(opts.Params)
-
- url := objectURL(c, opts.Container, opts.Name) + query
- _, err := perigee.Request("DELETE", url, perigee.Options{
- MoreHeaders: h,
- OkCodes: []int{204},
- })
- return err
-}
-
-// Get is a function that retrieves the metadata of an object. To extract just the custom
-// metadata, pass the GetResult response to the ExtractMetadata function.
-func Get(c *gophercloud.ServiceClient, opts GetOpts) (GetResult, error) {
- h := c.Provider.AuthenticatedHeaders()
-
- url := objectURL(c, opts.Container, opts.Name)
- resp, err := perigee.Request("HEAD", url, perigee.Options{
- MoreHeaders: h,
- OkCodes: []int{204},
- })
- return &resp.HttpResponse, err
-}
-
-// Update is a function that creates, updates, or deletes an object's metadata.
-func Update(c *gophercloud.ServiceClient, opts UpdateOpts) error {
- h := c.Provider.AuthenticatedHeaders()
-
- for k, v := range opts.Headers {
+ for k, v := range headers {
h[k] = v
}
@@ -177,8 +182,93 @@
h["X-Object-Meta-"+k] = v
}
- url := objectURL(c, opts.Container, opts.Name)
- _, err := perigee.Request("POST", url, perigee.Options{
+ url := objectURL(c, containerName, objectName)
+ _, err = perigee.Request("COPY", url, perigee.Options{
+ MoreHeaders: h,
+ OkCodes: []int{201},
+ })
+ return err
+}
+
+// DeleteOpts is a structure that holds parameters for deleting an object.
+type DeleteOpts struct {
+ MultipartManifest string `q:"multipart-manifest"`
+}
+
+// Delete is a function that deletes an object.
+func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts DeleteOpts) error {
+ h := c.Provider.AuthenticatedHeaders()
+
+ query, err := gophercloud.BuildQueryString(opts)
+ if err != nil {
+ return err
+ }
+
+ url := objectURL(c, containerName, objectName) + query
+ _, err = perigee.Request("DELETE", url, perigee.Options{
+ MoreHeaders: h,
+ OkCodes: []int{204},
+ })
+ return err
+}
+
+// GetOpts is a structure that holds parameters for getting an object's metadata.
+type GetOpts struct {
+ Expires string `q:"expires"`
+ Signature string `q:"signature"`
+}
+
+// Get is a function that retrieves the metadata of an object. To extract just the custom
+// metadata, pass the GetResult response to the ExtractMetadata function.
+func Get(c *gophercloud.ServiceClient, containerName, objectName string, opts GetOpts) GetResult {
+ var gr GetResult
+ query, err := gophercloud.BuildQueryString(opts)
+ if err != nil {
+ gr.Err = err
+ return gr
+ }
+
+ url := objectURL(c, containerName, objectName) + query
+ resp, err := perigee.Request("HEAD", url, perigee.Options{
+ MoreHeaders: c.Provider.AuthenticatedHeaders(),
+ OkCodes: []int{200, 204},
+ })
+ gr.Err = err
+ gr.Resp = &resp.HttpResponse
+ return gr
+}
+
+// UpdateOpts is a structure that holds parameters for updating, creating, or deleting an
+// object's metadata.
+type UpdateOpts struct {
+ Metadata map[string]string
+ ContentDisposition string `h:"Content-Disposition"`
+ ContentEncoding string `h:"Content-Encoding"`
+ ContentType string `h:"Content-Type"`
+ DeleteAfter int `h:"X-Delete-After"`
+ DeleteAt int `h:"X-Delete-At"`
+ DetectContentType bool `h:"X-Detect-Content-Type"`
+}
+
+// Update is a function that creates, updates, or deletes an object's metadata.
+func Update(c *gophercloud.ServiceClient, containerName, objectName string, opts UpdateOpts) error {
+ h := c.Provider.AuthenticatedHeaders()
+
+ headers, err := gophercloud.BuildHeaders(opts)
+ if err != nil {
+ return nil
+ }
+
+ for k, v := range headers {
+ h[k] = v
+ }
+
+ for k, v := range opts.Metadata {
+ h["X-Object-Meta-"+k] = v
+ }
+
+ url := objectURL(c, containerName, objectName)
+ _, err = perigee.Request("POST", url, perigee.Options{
MoreHeaders: h,
OkCodes: []int{202},
})