struct opts -> interface opts (object storage)
diff --git a/openstack/objectstorage/v1/accounts/requests.go b/openstack/objectstorage/v1/accounts/requests.go
index b30439c..55fcb05 100644
--- a/openstack/objectstorage/v1/accounts/requests.go
+++ b/openstack/objectstorage/v1/accounts/requests.go
@@ -5,20 +5,33 @@
 	"github.com/rackspace/gophercloud"
 )
 
-// GetOpts is a structure that contains parameters for getting an account's metadata.
+// GetOptsBuilder allows extensions to add additional headers to the Get
+// request.
+type GetOptsBuilder interface {
+	ToAccountGetMap() (map[string]string, error)
+}
+
+// GetOpts is a structure that contains parameters for getting an account's
+// metadata.
 type GetOpts struct {
 	Newest bool `h:"X-Newest"`
 }
 
-// Get is a function that retrieves an account's metadata. To extract just the custom
-// metadata, call the ExtractMetadata method on the GetResult. To extract all the headers that are
-// returned (including the metadata), call the ExtractHeaders method on the GetResult.
-func Get(c *gophercloud.ServiceClient, opts *GetOpts) GetResult {
+// ToAccountGetMap formats a GetOpts into a map[string]string of headers.
+func (opts GetOpts) ToAccountGetMap() (map[string]string, error) {
+	return gophercloud.BuildHeaders(opts)
+}
+
+// Get is a function that retrieves an account's metadata. To extract just the
+// custom metadata, call the ExtractMetadata method on the GetResult. To extract
+// all the headers that are returned (including the metadata), call the
+// ExtractHeaders method on the GetResult.
+func Get(c *gophercloud.ServiceClient, opts GetOptsBuilder) GetResult {
 	var res GetResult
 	h := c.Provider.AuthenticatedHeaders()
 
 	if opts != nil {
-		headers, err := gophercloud.BuildHeaders(opts)
+		headers, err := opts.ToAccountGetMap()
 		if err != nil {
 			res.Err = err
 			return res
@@ -38,8 +51,14 @@
 	return res
 }
 
-// UpdateOpts is a structure that contains parameters for updating, creating, or deleting an
-// account's metadata.
+// UpdateOptsBuilder allows extensions to add additional headers to the Update
+// request.
+type UpdateOptsBuilder interface {
+	ToAccountUpdateMap() (map[string]string, error)
+}
+
+// UpdateOpts is a structure that contains parameters for updating, creating, or
+// deleting an account's metadata.
 type UpdateOpts struct {
 	Metadata          map[string]string
 	ContentType       string `h:"Content-Type"`
@@ -48,14 +67,27 @@
 	TempURLKey2       string `h:"X-Account-Meta-Temp-URL-Key-2"`
 }
 
-// Update is a function that creates, updates, or deletes an account's metadata. To extract the
-// headers returned, call the ExtractHeaders method on the UpdateResult.
-func Update(c *gophercloud.ServiceClient, opts *UpdateOpts) UpdateResult {
+// ToAccountUpdateMap formats an UpdateOpts into a map[string]string of headers.
+func (opts UpdateOpts) ToAccountUpdateMap() (map[string]string, error) {
+	headers, err := gophercloud.BuildHeaders(opts)
+	if err != nil {
+		return nil, err
+	}
+	for k, v := range opts.Metadata {
+		headers["X-Account-Meta-"+k] = v
+	}
+	return headers, err
+}
+
+// Update is a function that creates, updates, or deletes an account's metadata.
+// To extract the headers returned, call the ExtractHeaders method on the
+// UpdateResult.
+func Update(c *gophercloud.ServiceClient, opts UpdateOptsBuilder) UpdateResult {
 	var res UpdateResult
 	h := c.Provider.AuthenticatedHeaders()
 
 	if opts != nil {
-		headers, err := gophercloud.BuildHeaders(opts)
+		headers, err := opts.ToAccountUpdateMap()
 		if err != nil {
 			res.Err = err
 			return res
@@ -63,10 +95,6 @@
 		for k, v := range headers {
 			h[k] = v
 		}
-
-		for k, v := range opts.Metadata {
-			h["X-Account-Meta-"+k] = v
-		}
 	}
 
 	resp, err := perigee.Request("POST", updateURL(c), perigee.Options{
diff --git a/openstack/objectstorage/v1/containers/requests.go b/openstack/objectstorage/v1/containers/requests.go
index d0d3781..afe7c7f 100644
--- a/openstack/objectstorage/v1/containers/requests.go
+++ b/openstack/objectstorage/v1/containers/requests.go
@@ -6,6 +6,12 @@
 	"github.com/rackspace/gophercloud/pagination"
 )
 
+// ListOptsBuilder allows extensions to add additional parameters to the List
+// request.
+type ListOptsBuilder interface {
+	ToContainerListParams() (bool, string, error)
+}
+
 // ListOpts is a structure that holds options for listing containers.
 type ListOpts struct {
 	Full      bool
@@ -17,24 +23,33 @@
 	Delimiter [1]byte `q:"delimiter"`
 }
 
-// List is a function that retrieves containers associated with the account as well as account
-// metadata. It returns a pager which can be iterated with the EachPage function.
-func List(c *gophercloud.ServiceClient, opts *ListOpts) pagination.Pager {
-	var headers map[string]string
+// ToContainerListParams formats a ListOpts into a query string and boolean
+// representing whether to list complete information for each container.
+func (opts ListOpts) ToContainerListParams() (bool, string, error) {
+	q, err := gophercloud.BuildQueryString(opts)
+	if err != nil {
+		return false, "", err
+	}
+	return opts.Full, q.String(), nil
+}
+
+// List is a function that retrieves containers associated with the account as
+// well as account metadata. It returns a pager which can be iterated with the
+// EachPage function.
+func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
+	headers := map[string]string{"Accept": "text/plain", "Content-Type": "text/plain"}
 
 	url := listURL(c)
 	if opts != nil {
-		query, err := gophercloud.BuildQueryString(opts)
+		full, query, err := opts.ToContainerListParams()
 		if err != nil {
 			return pagination.Pager{Err: err}
 		}
-		url += query.String()
+		url += query
 
-		if !opts.Full {
-			headers = map[string]string{"Accept": "text/plain", "Content-Type": "text/plain"}
+		if full {
+			headers = map[string]string{"Accept": "application/json", "Content-Type": "application/json"}
 		}
-	} else {
-		headers = map[string]string{"Accept": "text/plain", "Content-Type": "text/plain"}
 	}
 
 	createPage := func(r pagination.LastHTTPResponse) pagination.Page {
@@ -48,6 +63,12 @@
 	return pager
 }
 
+// CreateOptsBuilder allows extensions to add additional parameters to the
+// Create request.
+type CreateOptsBuilder interface {
+	ToContainerCreateParams() (map[string]string, error)
+}
+
 // CreateOpts is a structure that holds parameters for creating a container.
 type CreateOpts struct {
 	Metadata          map[string]string
@@ -61,13 +82,25 @@
 	VersionsLocation  string `h:"X-Versions-Location"`
 }
 
+// ToContainerCreateParams formats a CreateOpts into a map of headers.
+func (opts CreateOpts) ToContainerCreateParams() (map[string]string, error) {
+	h, err := gophercloud.BuildHeaders(opts)
+	if err != nil {
+		return nil, err
+	}
+	for k, v := range opts.Metadata {
+		h["X-Container-Meta-"+k] = v
+	}
+	return h, nil
+}
+
 // Create is a function that creates a new container.
-func Create(c *gophercloud.ServiceClient, containerName string, opts *CreateOpts) CreateResult {
+func Create(c *gophercloud.ServiceClient, containerName string, opts CreateOptsBuilder) CreateResult {
 	var res CreateResult
 	h := c.Provider.AuthenticatedHeaders()
 
 	if opts != nil {
-		headers, err := gophercloud.BuildHeaders(opts)
+		headers, err := opts.ToContainerCreateParams()
 		if err != nil {
 			res.Err = err
 			return res
@@ -76,10 +109,6 @@
 		for k, v := range headers {
 			h[k] = v
 		}
-
-		for k, v := range opts.Metadata {
-			h["X-Container-Meta-"+k] = v
-		}
 	}
 
 	resp, err := perigee.Request("PUT", createURL(c, containerName), perigee.Options{
@@ -103,8 +132,14 @@
 	return res
 }
 
-// UpdateOpts is a structure that holds parameters for updating, creating, or deleting a
-// container's metadata.
+// UpdateOptsBuilder allows extensions to add additional parameters to the
+// Update request.
+type UpdateOptsBuilder interface {
+	ToContainerUpdateParams() (map[string]string, error)
+}
+
+// UpdateOpts is a structure that holds parameters for updating, creating, or
+// deleting a container's metadata.
 type UpdateOpts struct {
 	Metadata               map[string]string
 	ContainerRead          string `h:"X-Container-Read"`
@@ -117,13 +152,26 @@
 	VersionsLocation       string `h:"X-Versions-Location"`
 }
 
-// Update is a function that creates, updates, or deletes a container's metadata.
-func Update(c *gophercloud.ServiceClient, containerName string, opts *UpdateOpts) UpdateResult {
+// ToContainerUpdateParams formats a CreateOpts into a map of headers.
+func (opts UpdateOpts) ToContainerUpdateParams() (map[string]string, error) {
+	h, err := gophercloud.BuildHeaders(opts)
+	if err != nil {
+		return nil, err
+	}
+	for k, v := range opts.Metadata {
+		h["X-Container-Meta-"+k] = v
+	}
+	return h, nil
+}
+
+// Update is a function that creates, updates, or deletes a container's
+// metadata.
+func Update(c *gophercloud.ServiceClient, containerName string, opts UpdateOptsBuilder) UpdateResult {
 	var res UpdateResult
 	h := c.Provider.AuthenticatedHeaders()
 
 	if opts != nil {
-		headers, err := gophercloud.BuildHeaders(opts)
+		headers, err := opts.ToContainerUpdateParams()
 		if err != nil {
 			res.Err = err
 			return res
@@ -132,10 +180,6 @@
 		for k, v := range headers {
 			h[k] = v
 		}
-
-		for k, v := range opts.Metadata {
-			h["X-Container-Meta-"+k] = v
-		}
 	}
 
 	resp, err := perigee.Request("POST", updateURL(c, containerName), perigee.Options{
@@ -147,8 +191,9 @@
 	return res
 }
 
-// Get is a function that retrieves the metadata of a container. To extract just the custom
-// metadata, pass the GetResult response to the ExtractMetadata function.
+// Get is a function that retrieves the metadata of a container. To extract just
+// the custom metadata, pass the GetResult response to the ExtractMetadata
+// function.
 func Get(c *gophercloud.ServiceClient, containerName string) GetResult {
 	var res GetResult
 	resp, err := perigee.Request("HEAD", getURL(c, containerName), perigee.Options{
diff --git a/openstack/objectstorage/v1/objects/requests.go b/openstack/objectstorage/v1/objects/requests.go
index 15ec5c7..77b8380 100644
--- a/openstack/objectstorage/v1/objects/requests.go
+++ b/openstack/objectstorage/v1/objects/requests.go
@@ -10,6 +10,12 @@
 	"github.com/rackspace/gophercloud/pagination"
 )
 
+// ListOptsBuilder allows extensions to add additional parameters to the List
+// request.
+type ListOptsBuilder interface {
+	ToObjectListParams() (bool, string, error)
+}
+
 // ListOpts is a structure that holds parameters for listing objects.
 type ListOpts struct {
 	Full      bool
@@ -22,26 +28,34 @@
 	Path      string  `q:"path"`
 }
 
+// ToObjectListParams formats a ListOpts into a query string and boolean
+// representing whether to list complete information for each object.
+func (opts ListOpts) ToObjectListParams() (bool, string, error) {
+	q, err := gophercloud.BuildQueryString(opts)
+	if err != nil {
+		return false, "", err
+	}
+	return opts.Full, q.String(), nil
+}
+
 // 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, containerName string, opts *ListOpts) pagination.Pager {
-	var headers map[string]string
+func List(c *gophercloud.ServiceClient, containerName string, opts ListOptsBuilder) pagination.Pager {
+	headers := map[string]string{"Accept": "text/plain", "Content-Type": "text/plain"}
 
 	url := listURL(c, containerName)
 	if opts != nil {
-		query, err := gophercloud.BuildQueryString(opts)
+		full, query, err := opts.ToObjectListParams()
 		if err != nil {
 			fmt.Printf("Error building query string: %v", err)
 			return pagination.Pager{Err: err}
 		}
-		url += query.String()
+		url += query
 
-		if !opts.Full {
-			headers = map[string]string{"Accept": "text/plain", "Content-Type": "text/plain"}
+		if full {
+			headers = map[string]string{"Accept": "application/json", "Content-Type": "application/json"}
 		}
-	} else {
-		headers = map[string]string{"Accept": "text/plain", "Content-Type": "text/plain"}
 	}
 
 	createPage := func(r pagination.LastHTTPResponse) pagination.Page {
@@ -55,6 +69,12 @@
 	return pager
 }
 
+// DownloadOptsBuilder allows extensions to add additional parameters to the
+// Download request.
+type DownloadOptsBuilder interface {
+	ToObjectDownloadParams() (map[string]string, string, error)
+}
+
 // DownloadOpts is a structure that holds parameters for downloading an object.
 type DownloadOpts struct {
 	IfMatch           string    `h:"If-Match"`
@@ -67,17 +87,31 @@
 	Signature         string    `q:"signature"`
 }
 
+// ToObjectDownloadParams formats a DownloadOpts into a query string and map of
+// headers.
+func (opts ListOpts) ToObjectDownloadParams() (map[string]string, string, error) {
+	q, err := gophercloud.BuildQueryString(opts)
+	if err != nil {
+		return nil, "", err
+	}
+	h, err := gophercloud.BuildHeaders(opts)
+	if err != nil {
+		return nil, q.String(), err
+	}
+	return h, q.String(), nil
+}
+
 // 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, containerName, objectName string, opts *DownloadOpts) DownloadResult {
+// To extract just the content, pass the DownloadResult response to the
+// ExtractContent function.
+func Download(c *gophercloud.ServiceClient, containerName, objectName string, opts DownloadOptsBuilder) DownloadResult {
 	var res DownloadResult
 
 	url := downloadURL(c, containerName, objectName)
 	h := c.Provider.AuthenticatedHeaders()
 
 	if opts != nil {
-		headers, err := gophercloud.BuildHeaders(opts)
+		headers, query, err := opts.ToObjectDownloadParams()
 		if err != nil {
 			res.Err = err
 			return res
@@ -87,12 +121,7 @@
 			h[k] = v
 		}
 
-		query, err := gophercloud.BuildQueryString(opts)
-		if err != nil {
-			res.Err = err
-			return res
-		}
-		url += query.String()
+		url += query
 	}
 
 	resp, err := perigee.Request("GET", url, perigee.Options{
@@ -104,6 +133,12 @@
 	return res
 }
 
+// CreateOptsBuilder allows extensions to add additional parameters to the
+// Create request.
+type CreateOptsBuilder interface {
+	ToObjectCreateParams() (map[string]string, string, error)
+}
+
 // CreateOpts is a structure that holds parameters for creating an object.
 type CreateOpts struct {
 	Metadata           map[string]string
@@ -124,8 +159,27 @@
 	Signature          string `q:"signature"`
 }
 
+// ToObjectCreateParams formats a CreateOpts into a query string and map of
+// headers.
+func (opts CreateOpts) ToObjectCreateParams() (map[string]string, string, error) {
+	q, err := gophercloud.BuildQueryString(opts)
+	if err != nil {
+		return nil, "", err
+	}
+	h, err := gophercloud.BuildHeaders(opts)
+	if err != nil {
+		return nil, q.String(), err
+	}
+
+	for k, v := range opts.Metadata {
+		h["X-Object-Meta-"+k] = v
+	}
+
+	return h, q.String(), nil
+}
+
 // Create is a function that creates a new object or replaces an existing object.
-func Create(c *gophercloud.ServiceClient, containerName, objectName string, content io.Reader, opts *CreateOpts) CreateResult {
+func Create(c *gophercloud.ServiceClient, containerName, objectName string, content io.Reader, opts CreateOptsBuilder) CreateResult {
 	var res CreateResult
 	var reqBody []byte
 
@@ -133,7 +187,7 @@
 	h := c.Provider.AuthenticatedHeaders()
 
 	if opts != nil {
-		headers, err := gophercloud.BuildHeaders(opts)
+		headers, query, err := opts.ToObjectCreateParams()
 		if err != nil {
 			res.Err = err
 			return res
@@ -143,17 +197,7 @@
 			h[k] = v
 		}
 
-		for k, v := range opts.Metadata {
-			h["X-Object-Meta-"+k] = v
-		}
-
-		query, err := gophercloud.BuildQueryString(opts)
-		if err != nil {
-			res.Err = err
-			return res
-		}
-
-		url += query.String()
+		url += query
 	}
 
 	if content != nil {
@@ -175,7 +219,14 @@
 	return res
 }
 
-// CopyOpts is a structure that holds parameters for copying one object to another.
+// CopyOptsBuilder allows extensions to add additional parameters to the
+// Copy request.
+type CopyOptsBuilder interface {
+	ToObjectCopyParams() (map[string]string, error)
+}
+
+// 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"`
@@ -184,28 +235,36 @@
 	Destination        string `h:"Destination,required"`
 }
 
+// ToObjectCopyParams formats a CopyOpts into a map of headers.
+func (opts CopyOpts) ToObjectCopyParams() (map[string]string, error) {
+	if opts.Destination == "" {
+		return nil, fmt.Errorf("Required CopyOpts field 'Destination' not set.")
+	}
+	h, err := gophercloud.BuildHeaders(opts)
+	if err != nil {
+		return nil, err
+	}
+	for k, v := range opts.Metadata {
+		h["X-Object-Meta-"+k] = v
+	}
+	return h, nil
+}
+
 // Copy is a function that copies one object to another.
-func Copy(c *gophercloud.ServiceClient, containerName, objectName string, opts *CopyOpts) CopyResult {
+func Copy(c *gophercloud.ServiceClient, containerName, objectName string, opts CopyOptsBuilder) CopyResult {
 	var res CopyResult
 	h := c.Provider.AuthenticatedHeaders()
 
-	if opts == nil {
-		res.Err = fmt.Errorf("Required CopyOpts field 'Destination' not set.")
-		return res
-	}
-	headers, err := gophercloud.BuildHeaders(opts)
+	headers, err := opts.ToObjectCopyParams()
 	if err != nil {
 		res.Err = err
 		return res
 	}
+
 	for k, v := range headers {
 		h[k] = v
 	}
 
-	for k, v := range opts.Metadata {
-		h["X-Object-Meta-"+k] = v
-	}
-
 	url := copyURL(c, containerName, objectName)
 	resp, err := perigee.Request("COPY", url, perigee.Options{
 		MoreHeaders: h,
@@ -215,23 +274,38 @@
 	return res
 }
 
+// DeleteOptsBuilder allows extensions to add additional parameters to the
+// Delete request.
+type DeleteOptsBuilder interface {
+	ToObjectDeleteParams() (string, error)
+}
+
 // DeleteOpts is a structure that holds parameters for deleting an object.
 type DeleteOpts struct {
 	MultipartManifest string `q:"multipart-manifest"`
 }
 
+// ToObjectDeleteParams formats a DeleteOpts into a query string.
+func (opts DeleteOpts) ToObjectDeleteParams() (string, error) {
+	q, err := gophercloud.BuildQueryString(opts)
+	if err != nil {
+		return "", err
+	}
+	return q.String(), nil
+}
+
 // Delete is a function that deletes an object.
-func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts *DeleteOpts) DeleteResult {
+func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts DeleteOptsBuilder) DeleteResult {
 	var res DeleteResult
 	url := deleteURL(c, containerName, objectName)
 
 	if opts != nil {
-		query, err := gophercloud.BuildQueryString(opts)
+		query, err := opts.ToObjectDeleteParams()
 		if err != nil {
 			res.Err = err
 			return res
 		}
-		url += query.String()
+		url += query
 	}
 
 	resp, err := perigee.Request("DELETE", url, perigee.Options{
@@ -243,25 +317,40 @@
 	return res
 }
 
+// GetOptsBuilder allows extensions to add additional parameters to the
+// Get request.
+type GetOptsBuilder interface {
+	ToObjectGetParams() (string, error)
+}
+
 // GetOpts is a structure that holds parameters for getting an object's metadata.
 type GetOpts struct {
 	Expires   string `q:"expires"`
 	Signature string `q:"signature"`
 }
 
+// ToObjectGetParams formats a GetOpts into a query string.
+func (opts GetOpts) ToObjectGetParams() (string, error) {
+	q, err := gophercloud.BuildQueryString(opts)
+	if err != nil {
+		return "", err
+	}
+	return q.String(), nil
+}
+
 // 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 {
+func Get(c *gophercloud.ServiceClient, containerName, objectName string, opts GetOptsBuilder) GetResult {
 	var res GetResult
 	url := getURL(c, containerName, objectName)
 
 	if opts != nil {
-		query, err := gophercloud.BuildQueryString(opts)
+		query, err := opts.ToObjectGetParams()
 		if err != nil {
 			res.Err = err
 			return res
 		}
-		url += query.String()
+		url += query
 	}
 
 	resp, err := perigee.Request("HEAD", url, perigee.Options{
@@ -273,6 +362,12 @@
 	return res
 }
 
+// UpdateOptsBuilder allows extensions to add additional parameters to the
+// Update request.
+type UpdateOptsBuilder interface {
+	ToObjectUpdateParams() (map[string]string, error)
+}
+
 // UpdateOpts is a structure that holds parameters for updating, creating, or deleting an
 // object's metadata.
 type UpdateOpts struct {
@@ -285,13 +380,25 @@
 	DetectContentType  bool   `h:"X-Detect-Content-Type"`
 }
 
+// ToObjectUpdateParams formats a UpdateOpts into a map of headers.
+func (opts UpdateOpts) ToObjectUpdateParams() (map[string]string, error) {
+	h, err := gophercloud.BuildHeaders(opts)
+	if err != nil {
+		return nil, err
+	}
+	for k, v := range opts.Metadata {
+		h["X-Object-Meta-"+k] = v
+	}
+	return h, nil
+}
+
 // Update is a function that creates, updates, or deletes an object's metadata.
-func Update(c *gophercloud.ServiceClient, containerName, objectName string, opts *UpdateOpts) UpdateResult {
+func Update(c *gophercloud.ServiceClient, containerName, objectName string, opts UpdateOptsBuilder) UpdateResult {
 	var res UpdateResult
 	h := c.Provider.AuthenticatedHeaders()
 
 	if opts != nil {
-		headers, err := gophercloud.BuildHeaders(opts)
+		headers, err := opts.ToObjectUpdateParams()
 		if err != nil {
 			res.Err = err
 			return res
@@ -300,10 +407,6 @@
 		for k, v := range headers {
 			h[k] = v
 		}
-
-		for k, v := range opts.Metadata {
-			h["X-Object-Meta-"+k] = v
-		}
 	}
 
 	url := updateURL(c, containerName, objectName)