From 0e685c1a6632f2f421713f677dd1ae691dedaa68 Mon Sep 17 00:00:00 2001 From: Stefan Majewsky Date: Thu, 3 May 2018 15:14:47 +0200 Subject: add configurable User-Agent to Schwift, Gopherschwift --- README.md | 8 +++++--- backend.go | 15 ++++++++++----- gopherschwift/package.go | 28 +++++++++++++++++++++++----- tests/shared_test.go | 2 +- version.go | 22 ++++++++++++++++++++++ 5 files changed, 61 insertions(+), 14 deletions(-) create mode 100644 version.go diff --git a/README.md b/README.md index b13b42b..970a6bf 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,9 @@ This is a Go client library for [OpenStack Swift](https://github.com/openstack/s frustrated with the inflexible API design of [`ncw/swift`](https://github.com/ncw/swift); see [near the bottom](#why-another-swift-client-library) for details. -

WARNING: This is in a pre-alpha stage and neither complete nor tested.

+This library is currently in **beta**: It's already used by some projects, and I'm working towards a +stable 1.0 version with API compatbility promises, but [a few things are still +missing](https://github.com/majewsky/schwift/issues/1). ## Installation @@ -29,7 +31,7 @@ authOptions, err := openstack.AuthOptionsFromEnv() provider, err := openstack.AuthenticatedClient(authOptions) client, err := openstack.NewObjectStorageV1(provider, gophercloud.EndpointOpts{}) -account, err := gopherschwift.Wrap(client) +account, err := gopherschwift.Wrap(client, nil) ``` To connect to Swift using Swift's built-in authentication: @@ -47,7 +49,7 @@ client, err := swauth.NewObjectStorageV1(provider, swauth.AuthOpts { Key: "password", }) -account, err := gopherschwift.Wrap(client) +account, err := gopherschwift.Wrap(client, nil) ``` From this point, follow the [API documentation](https://godoc.org/github.com/majewsky/schwift) for what you can do with diff --git a/backend.go b/backend.go index de07015..af2c1ef 100644 --- a/backend.go +++ b/backend.go @@ -34,10 +34,15 @@ type Backend interface { //the given URL. This is used by Account.SwitchAccount(). Clone(newEndpointURL string) Backend //Do executes the given HTTP request after adding to it the X-Auth-Token - //header containing the backend's current Keystone (or Swift auth) token. It - //may also set other headers, such as User-Agent. If the status code returned - //is 401, it shall attempt to acquire a new auth token and restart the - //request with the new token. + //header containing the backend's current Keystone (or Swift auth) token. If + //the status code returned is 401, it shall attempt to acquire a new auth + //token and restart the request with the new token. + // + //If the user has not supplied their own User-Agent string to the backend, + //the backend should use the schwift.DefaultUserAgent constant instead. Do(req *http.Request) (*http.Response, error) - //TODO add UserAgent argument to Do() } + +//DefaultUserAgent is the User-Agent string that Backend implementations should +//use if the user does not provide their own User-Agent string. +const DefaultUserAgent = "schwift/" + Version diff --git a/gopherschwift/package.go b/gopherschwift/package.go index bd47b8d..3889735 100644 --- a/gopherschwift/package.go +++ b/gopherschwift/package.go @@ -50,15 +50,30 @@ import ( "github.com/majewsky/schwift" ) +//Options contains additional options that can be passed to Wrap(). +type Options struct { + //If set, this User-Agent will be reported in HTTP requests instead of + //schwift.DefaultUserAgent. + UserAgent string +} + //Wrap creates a schwift.Account that uses the given service client as its //backend. The service client must refer to a Swift endpoint, i.e. it should //have been created by openstack.NewObjectStorageV1(). -func Wrap(client *gophercloud.ServiceClient) (*schwift.Account, error) { - return schwift.InitializeAccount(&backend{client}) +func Wrap(client *gophercloud.ServiceClient, opts *Options) (*schwift.Account, error) { + b := &backend{ + c: client, + userAgent: schwift.DefaultUserAgent, + } + if opts != nil && opts.UserAgent != "" { + b.userAgent = opts.UserAgent + } + return schwift.InitializeAccount(b) } type backend struct { - c *gophercloud.ServiceClient + c *gophercloud.ServiceClient + userAgent string } func (g *backend) EndpointURL() string { @@ -68,7 +83,10 @@ func (g *backend) EndpointURL() string { func (g *backend) Clone(newEndpointURL string) schwift.Backend { clonedClient := *g.c clonedClient.Endpoint = newEndpointURL - return &backend{&clonedClient} + return &backend{ + c: &clonedClient, + userAgent: g.userAgent, + } } func (g *backend) Do(req *http.Request) (*http.Response, error) { @@ -78,10 +96,10 @@ func (g *backend) Do(req *http.Request) (*http.Response, error) { func (g *backend) do(req *http.Request, afterReauth bool) (*http.Response, error) { provider := g.c.ProviderClient - req.Header.Set("User-Agent", provider.UserAgent.Join()) for key, value := range provider.AuthenticatedHeaders() { req.Header.Set(key, value) } + req.Header.Set("User-Agent", g.userAgent) resp, err := provider.HTTPClient.Do(req) if err != nil { diff --git a/tests/shared_test.go b/tests/shared_test.go index c6b15e4..df9092e 100644 --- a/tests/shared_test.go +++ b/tests/shared_test.go @@ -71,7 +71,7 @@ func testWithAccount(t *testing.T, testCode func(a *schwift.Account)) { } } - account, err := gopherschwift.Wrap(client) + account, err := gopherschwift.Wrap(client, nil) if err != nil { t.Error(err.Error()) return diff --git a/version.go b/version.go new file mode 100644 index 0000000..17f07d7 --- /dev/null +++ b/version.go @@ -0,0 +1,22 @@ +/****************************************************************************** +* +* Copyright 2018 Stefan Majewsky +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +******************************************************************************/ + +package schwift + +//Version contains the version number of Schwift. +const Version = "1.0-beta" -- cgit v1.2.3