add UserAgent field and methods to ProviderClient
diff --git a/provider_client.go b/provider_client.go
index 3316733..09e9344 100644
--- a/provider_client.go
+++ b/provider_client.go
@@ -7,8 +7,32 @@
"io"
"io/ioutil"
"net/http"
+ "strings"
)
+// DefaultUserAgent is the default User-Agent string set in the request header.
+const DefaultUserAgent = "gophercloud/v1.0"
+
+// UserAgent represents a User-Agent header.
+type UserAgent struct {
+ // prepend is the slice of User-Agent strings to prepend to DefaultUserAgent.
+ // All the strings to prepend are accumulated and prepended in the Join method.
+ prepend []string
+}
+
+// Prepend prepends a user-defined string to the default User-Agent string. Users
+// may pass in one or more strings to prepend.
+func (ua *UserAgent) Prepend(s ...string) {
+ ua.prepend = append(s, ua.prepend...)
+}
+
+// Join concatenates all the user-defined User-Agend strings with the default
+// Gophercloud User-Agent string.
+func (ua *UserAgent) Join() string {
+ uaSlice := append(ua.prepend, DefaultUserAgent)
+ return strings.Join(uaSlice, " ")
+}
+
// ProviderClient stores details that are required to interact with any
// services within a specific provider's API.
//
@@ -36,6 +60,9 @@
// HTTPClient allows users to interject arbitrary http, https, or other transit behaviors.
HTTPClient http.Client
+
+ // UserAgent represents the User-Agent header in the HTTP request.
+ UserAgent UserAgent
}
// AuthenticatedHeaders returns a map of HTTP headers that are common for all
@@ -97,7 +124,6 @@
// Derive the content body by either encoding an arbitrary object as JSON, or by taking a provided
// io.Reader as-is. Default the content-type to application/json.
-
if options.JSONBody != nil {
if options.RawBody != nil {
panic("Please provide only one of JSONBody or RawBody to gophercloud.Request().")
@@ -117,7 +143,6 @@
}
// Construct the http.Request.
-
req, err := http.NewRequest(method, url, body)
if err != nil {
return nil, err
@@ -125,7 +150,6 @@
// Populate the request headers. Apply options.MoreHeaders last, to give the caller the chance to
// modify or omit any header.
-
if contentType != nil {
req.Header.Set("Content-Type", *contentType)
}
@@ -146,15 +170,16 @@
}
}
- // Issue the request.
+ // Set user-agent header
+ req.Header.Set("User-Agent", client.UserAgent.Join())
+ // Issue the request.
resp, err := client.HTTPClient.Do(req)
if err != nil {
return nil, err
}
// Validate the response code, if requested to do so.
-
if options.OkCodes != nil {
var ok bool
for _, code := range options.OkCodes {
@@ -177,7 +202,6 @@
}
// Parse the response body as JSON, if requested to do so.
-
if options.JSONResponse != nil {
defer resp.Body.Close()
json.NewDecoder(resp.Body).Decode(options.JSONResponse)