Use result structs for server requests.
diff --git a/openstack/compute/v2/servers/requests.go b/openstack/compute/v2/servers/requests.go
index da93ff1..3b23be5 100644
--- a/openstack/compute/v2/servers/requests.go
+++ b/openstack/compute/v2/servers/requests.go
@@ -36,11 +36,6 @@
 	return servers[len(servers)-1].ID, nil
 }
 
-// ServerResult abstracts a single server description, as returned by the OpenStack provider.
-// As OpenStack extensions may freely alter the response bodies of the structures returned to the client,
-// you may only safely access the data provided through separate, type-safe accessors or methods.
-type ServerResult map[string]interface{}
-
 // List makes a request against the API to list servers accessible to you.
 func List(client *gophercloud.ServiceClient) pagination.Pager {
 	createPage := func(r pagination.LastHTTPResponse) pagination.Page {
@@ -53,17 +48,17 @@
 }
 
 // Create requests a server to be provisioned to the user in the current tenant.
-func Create(client *gophercloud.ServiceClient, opts map[string]interface{}) (ServerResult, error) {
-	var sr ServerResult
-	_, err := perigee.Request("POST", getListURL(client), perigee.Options{
-		Results: &sr,
+func Create(client *gophercloud.ServiceClient, opts map[string]interface{}) CreateResult {
+	var result CreateResult
+	_, result.Err = perigee.Request("POST", getListURL(client), perigee.Options{
+		Results: &result.Resp,
 		ReqBody: map[string]interface{}{
 			"server": opts,
 		},
 		MoreHeaders: client.Provider.AuthenticatedHeaders(),
 		OkCodes:     []int{202},
 	})
-	return sr, err
+	return result
 }
 
 // Delete requests that a server previously provisioned be removed from your account.
@@ -76,26 +71,26 @@
 }
 
 // Get requests details on a single server, by ID.
-func Get(client *gophercloud.ServiceClient, id string) (ServerResult, error) {
-	var sr ServerResult
-	_, err := perigee.Request("GET", getServerURL(client, id), perigee.Options{
-		Results:     &sr,
+func Get(client *gophercloud.ServiceClient, id string) GetResult {
+	var result GetResult
+	_, result.Err = perigee.Request("GET", getServerURL(client, id), perigee.Options{
+		Results:     &result.Resp,
 		MoreHeaders: client.Provider.AuthenticatedHeaders(),
 	})
-	return sr, err
+	return result
 }
 
 // Update requests that various attributes of the indicated server be changed.
-func Update(client *gophercloud.ServiceClient, id string, opts map[string]interface{}) (ServerResult, error) {
-	var sr ServerResult
-	_, err := perigee.Request("PUT", getServerURL(client, id), perigee.Options{
-		Results: &sr,
+func Update(client *gophercloud.ServiceClient, id string, opts map[string]interface{}) UpdateResult {
+	var result UpdateResult
+	_, result.Err = perigee.Request("PUT", getServerURL(client, id), perigee.Options{
+		Results: &result.Resp,
 		ReqBody: map[string]interface{}{
 			"server": opts,
 		},
 		MoreHeaders: client.Provider.AuthenticatedHeaders(),
 	})
-	return sr, err
+	return result
 }
 
 // ChangeAdminPassword alters the administrator or root password for a specified server.
@@ -194,39 +189,43 @@
 //
 // Rebuild returns a server result as though you had called GetDetail() on the server's ID.
 // The information, however, refers to the new server, not the old.
-func Rebuild(client *gophercloud.ServiceClient, id, name, password, imageRef string, additional map[string]interface{}) (ServerResult, error) {
-	var sr ServerResult
+func Rebuild(client *gophercloud.ServiceClient, id, name, password, imageRef string, additional map[string]interface{}) RebuildResult {
+	var result RebuildResult
 
 	if id == "" {
-		return sr, &ErrArgument{
+		result.Err = &ErrArgument{
 			Function: "Rebuild",
 			Argument: "id",
 			Value:    "",
 		}
+		return result
 	}
 
 	if name == "" {
-		return sr, &ErrArgument{
+		result.Err = &ErrArgument{
 			Function: "Rebuild",
 			Argument: "name",
 			Value:    "",
 		}
+		return result
 	}
 
 	if password == "" {
-		return sr, &ErrArgument{
+		result.Err = &ErrArgument{
 			Function: "Rebuild",
 			Argument: "password",
 			Value:    "",
 		}
+		return result
 	}
 
 	if imageRef == "" {
-		return sr, &ErrArgument{
+		result.Err = &ErrArgument{
 			Function: "Rebuild",
 			Argument: "imageRef",
 			Value:    "",
 		}
+		return result
 	}
 
 	if additional == nil {
@@ -237,17 +236,17 @@
 	additional["imageRef"] = imageRef
 	additional["adminPass"] = password
 
-	_, err := perigee.Request("POST", getActionURL(client, id), perigee.Options{
+	_, result.Err = perigee.Request("POST", getActionURL(client, id), perigee.Options{
 		ReqBody: struct {
 			R map[string]interface{} `json:"rebuild"`
 		}{
 			additional,
 		},
-		Results:     &sr,
+		Results:     &result.Resp,
 		MoreHeaders: client.Provider.AuthenticatedHeaders(),
 		OkCodes:     []int{202},
 	})
-	return sr, err
+	return result
 }
 
 // Resize instructs the provider to change the flavor of the server.
diff --git a/openstack/compute/v2/servers/requests_test.go b/openstack/compute/v2/servers/requests_test.go
index 3f5f2b4..fa1a2f5 100644
--- a/openstack/compute/v2/servers/requests_test.go
+++ b/openstack/compute/v2/servers/requests_test.go
@@ -88,20 +88,15 @@
 	})
 
 	client := serviceClient()
-	result, err := Create(client, map[string]interface{}{
+	actual, err := Create(client, map[string]interface{}{
 		"name":      "derp",
 		"imageRef":  "f90f6034-2570-4974-8351-6b49732ef2eb",
 		"flavorRef": "1",
-	})
+	}).Extract()
 	if err != nil {
 		t.Fatalf("Unexpected Create error: %v", err)
 	}
 
-	actual, err := ExtractServer(result)
-	if err != nil {
-		t.Fatalf("Unexpected ExtractServer error: %v", err)
-	}
-
 	equalServers(t, serverDerp, *actual)
 }
 
@@ -136,16 +131,11 @@
 	})
 
 	client := serviceClient()
-	response, err := Get(client, "1234asdf")
+	actual, err := Get(client, "1234asdf").Extract()
 	if err != nil {
 		t.Fatalf("Unexpected Get error: %v", err)
 	}
 
-	actual, err := ExtractServer(response)
-	if err != nil {
-		t.Fatalf("Unexpected ExtractServer error: %v", err)
-	}
-
 	equalServers(t, serverDerp, *actual)
 }
 
@@ -164,18 +154,13 @@
 	})
 
 	client := serviceClient()
-	response, err := Update(client, "1234asdf", map[string]interface{}{
+	actual, err := Update(client, "1234asdf", map[string]interface{}{
 		"name": "new-name",
-	})
+	}).Extract()
 	if err != nil {
 		t.Fatalf("Unexpected Update error: %v", err)
 	}
 
-	actual, err := ExtractServer(response)
-	if err != nil {
-		t.Fatalf("Unexpected ExtractServer error: %v", err)
-	}
-
 	equalServers(t, serverDerp, *actual)
 }
 
@@ -241,19 +226,15 @@
 	})
 
 	client := serviceClient()
-	response, err := Rebuild(client,
+	actual, err := Rebuild(client,
 		"1234asdf", "new-name", "swordfish",
 		"http://104.130.131.164:8774/fcad67a6189847c4aecfa3c81a05783b/images/f90f6034-2570-4974-8351-6b49732ef2eb",
-		map[string]interface{}{"accessIPv4": "1.2.3.4"})
+		map[string]interface{}{"accessIPv4": "1.2.3.4"},
+	).Extract()
 	if err != nil {
 		t.Fatalf("Unexpected Rebuild error: %v", err)
 	}
 
-	actual, err := ExtractServer(response)
-	if err != nil {
-		t.Fatalf("Unexpected ExtractServer error: %v", err)
-	}
-
 	equalServers(t, serverDerp, *actual)
 }
 
diff --git a/openstack/compute/v2/servers/servers.go b/openstack/compute/v2/servers/results.go
similarity index 66%
rename from openstack/compute/v2/servers/servers.go
rename to openstack/compute/v2/servers/results.go
index fbf50c3..8e967f0 100644
--- a/openstack/compute/v2/servers/servers.go
+++ b/openstack/compute/v2/servers/results.go
@@ -4,6 +4,7 @@
 	"errors"
 
 	"github.com/mitchellh/mapstructure"
+	"github.com/rackspace/gophercloud"
 	"github.com/rackspace/gophercloud/pagination"
 )
 
@@ -64,6 +65,60 @@
 	AdminPass string `mapstructure:"adminPass"`
 }
 
+// extractServer interprets the result of a call expected to return data on a single server.
+func extractServer(r gophercloud.CommonResult) (*Server, error) {
+	if r.Err != nil {
+		return nil, r.Err
+	}
+
+	var response struct {
+		Server Server `mapstructure:"server"`
+	}
+
+	err := mapstructure.Decode(r.Resp, &response)
+	return &response.Server, err
+}
+
+// CreateResult temporarily contains the response from a Create call.
+type CreateResult struct {
+	gophercloud.CommonResult
+}
+
+// Extract interprets a CreateResult as a Server, if possible.
+func (r CreateResult) Extract() (*Server, error) {
+	return extractServer(r.CommonResult)
+}
+
+// GetResult temporarily contains the response from a Get call.
+type GetResult struct {
+	gophercloud.CommonResult
+}
+
+// Extract interprets a GetResult as a Server, if possible.
+func (r GetResult) Extract() (*Server, error) {
+	return extractServer(r.CommonResult)
+}
+
+// UpdateResult temporarily contains the response from an Update call.
+type UpdateResult struct {
+	gophercloud.CommonResult
+}
+
+// Extract interprets an UpdateResult as a Server, if possible.
+func (r UpdateResult) Extract() (*Server, error) {
+	return extractServer(r.CommonResult)
+}
+
+// RebuildResult temporarily contains the response from a Rebuild call.
+type RebuildResult struct {
+	gophercloud.CommonResult
+}
+
+// Extract interprets a RebuildResult as a Server, if possible.
+func (r RebuildResult) Extract() (*Server, error) {
+	return extractServer(r.CommonResult)
+}
+
 // ExtractServers interprets the results of a single page from a List() call, producing a slice of Server entities.
 func ExtractServers(page pagination.Page) ([]Server, error) {
 	casted := page.(ListPage).Body
@@ -74,15 +129,3 @@
 	err := mapstructure.Decode(casted, &response)
 	return response.Servers, err
 }
-
-// ExtractServer interprets the result of a call expected to return data on a single server.
-func ExtractServer(sr ServerResult) (*Server, error) {
-	so, ok := sr["server"]
-	if !ok {
-		return nil, ErrCannotInterpet
-	}
-	serverObj := so.(map[string]interface{})
-	s := new(Server)
-	err := mapstructure.Decode(serverObj, s)
-	return s, err
-}
diff --git a/openstack/compute/v2/servers/servers_test.go b/openstack/compute/v2/servers/servers_test.go
index 9127991..590fc8b 100644
--- a/openstack/compute/v2/servers/servers_test.go
+++ b/openstack/compute/v2/servers/servers_test.go
@@ -1,192 +1,10 @@
 package servers
 
 import (
-	"encoding/json"
 	"reflect"
 	"testing"
 )
 
-// Taken from: http://docs.openstack.org/api/openstack-compute/2/content/List_Servers-d1e2078.html
-const goodListServersResult = `
-{
-	"servers": [
-		{
-			"id": "52415800-8b69-11e0-9b19-734f6af67565",
-			"tenant_id": "1234",
-			"user_id": "5678",
-			"name": "sample-server",
-			"updated": "2010-10-10T12:00:00Z",
-			"created": "2010-08-10T12:00:00Z",
-			"hostId": "e4d909c290d0fb1ca068ffaddf22cbd0",
-			"status": "BUILD",
-			"progress": 60,
-			"accessIPv4": "67.23.10.132",
-			"accessIPv6": "::babe:67.23.10.132",
-			"image": {
-				"id": "52415800-8b69-11e0-9b19-734f6f006e54",
-				"links": [
-					{
-						"rel": "self",
-						"href": "http://servers.api.openstack.org/v2/1234/images/52415800-8b69-11e0-9b19-734f6f006e54"
-					},
-					{
-						"rel": "bookmark",
-						"href": "http://servers.api.openstack.org/1234/images/52415800-8b69-11e0-9b19-734f6f006e54"
-					}
-				]
-			},
-			"flavor": {
-				"id": "52415800-8b69-11e0-9b19-734f216543fd",
-				"links": [
-					{
-						"rel": "self",
-						"href": "http://servers.api.openstack.org/v2/1234/flavors/52415800-8b69-11e0-9b19-734f216543fd"
-					},
-					{
-						"rel": "bookmark",
-						"href": "http://servers.api.openstack.org/1234/flavors/52415800-8b69-11e0-9b19-734f216543fd"
-					}
-				]
-			},
-			"addresses": {
-				"public": [
-					{
-						"version": 4,
-						"addr": "67.23.10.132"
-					},
-					{
-						"version": 6,
-						"addr": "::babe:67.23.10.132"
-					},
-					{
-						"version": 4,
-						"addr": "67.23.10.131"
-					},
-					{
-						"version": 6,
-						"addr": "::babe:4317:0A83"
-					}
-				],
-				"private": [
-					{
-						"version": 4,
-						"addr": "10.176.42.16"
-					},
-					{
-						"version": 6,
-						"addr": "::babe:10.176.42.16"
-					}
-				]
-			},
-			"metadata": {
-				"Server Label": "Web Head 1",
-				"Image Version": "2.1"
-			},
-			"links": [
-				{
-					"rel": "self",
-					"href": "http://servers.api.openstack.org/v2/1234/servers/52415800-8b69-11e0-9b19-734f6af67565"
-				},
-				{
-					"rel": "bookmark",
-					"href": "http://servers.api.openstack.org/1234/servers/52415800-8b69-11e0-9b19-734f6af67565"
-				}
-			]
-		},
-		{
-			"id": "52415800-8b69-11e0-9b19-734f1f1350e5",
-			"user_id": "5678",
-			"name": "sample-server2",
-			"tenant_id": "1234",
-			"updated": "2010-10-10T12:00:00Z",
-			"created": "2010-08-10T12:00:00Z",
-			"hostId": "9e107d9d372bb6826bd81d3542a419d6",
-			"status": "ACTIVE",
-			"accessIPv4": "67.23.10.133",
-			"accessIPv6": "::babe:67.23.10.133",
-			"image": {
-				"id": "52415800-8b69-11e0-9b19-734f5736d2a2",
-				"links": [
-					{
-						"rel": "self",
-						"href": "http://servers.api.openstack.org/v2/1234/images/52415800-8b69-11e0-9b19-734f5736d2a2"
-					},
-					{
-						"rel": "bookmark",
-						"href": "http://servers.api.openstack.org/1234/images/52415800-8b69-11e0-9b19-734f5736d2a2"
-					}
-				]
-			},
-			"flavor": {
-				"id": "52415800-8b69-11e0-9b19-734f216543fd",
-				"links": [
-					{
-						"rel": "self",
-						"href": "http://servers.api.openstack.org/v2/1234/flavors/52415800-8b69-11e0-9b19-734f216543fd"
-					},
-					{
-						"rel": "bookmark",
-						"href": "http://servers.api.openstack.org/1234/flavors/52415800-8b69-11e0-9b19-734f216543fd"
-					}
-				]
-			},
-			"addresses": {
-				"public": [
-					{
-						"version": 4,
-						"addr": "67.23.10.133"
-					},
-					{
-						"version": 6,
-						"addr": "::babe:67.23.10.133"
-					}
-				],
-				"private": [
-					{
-						"version": 4,
-						"addr": "10.176.42.17"
-					},
-					{
-						"version": 6,
-						"addr": "::babe:10.176.42.17"
-					}
-				]
-			},
-			"metadata": {
-				"Server Label": "DB 1"
-			},
-			"links": [
-				{
-					"rel": "self",
-					"href": "http://servers.api.openstack.org/v2/1234/servers/52415800-8b69-11e0-9b19-734f1f1350e5"
-				},
-				{
-					"rel": "bookmark",
-					"href": "http://servers.api.openstack.org/1234/servers/52415800-8b69-11e0-9b19-734f1f1350e5"
-				}
-			]
-		}
-	]
-}
-`
-
-func TestExtractServers(t *testing.T) {
-	var listPage ListPage
-	err := json.Unmarshal([]byte(goodListServersResult), &listPage.MarkerPageBase.LastHTTPResponse.Body)
-	if err != nil {
-		t.Fatalf("Error decoding JSON fixture: %v", err)
-	}
-
-	svrs, err := ExtractServers(listPage)
-	if err != nil {
-		t.Fatalf("Error extracting servers: %v", err)
-	}
-
-	if len(svrs) != 2 {
-		t.Fatalf("Expected 2 servers; got %d", len(svrs))
-	}
-}
-
 // This provides more fine-grained failures when Servers differ, because Server structs are too damn big to compare by eye.
 // FIXME I should absolutely refactor this into a general-purpose thing in testhelper.
 func equalServers(t *testing.T, expected Server, actual Server) {