Explorar o código

requestdecorator: repurpose the package and rename to useragent

Signed-off-by: Tibor Vass <tibor@docker.com>
Tibor Vass %!s(int64=10) %!d(string=hai) anos
pai
achega
cf8c0d0f56

+ 0 - 2
pkg/requestdecorator/README.md

@@ -1,2 +0,0 @@
-This package provides helper functions for decorating a request with user agent
-versions, auth, meta headers.

+ 0 - 172
pkg/requestdecorator/requestdecorator.go

@@ -1,172 +0,0 @@
-// Package requestdecorator provides helper functions to decorate a request with
-// user agent versions, auth, meta headers.
-package requestdecorator
-
-import (
-	"errors"
-	"io"
-	"net/http"
-	"strings"
-
-	"github.com/Sirupsen/logrus"
-)
-
-var (
-	ErrNilRequest = errors.New("request cannot be nil")
-)
-
-// UAVersionInfo is used to model UserAgent versions.
-type UAVersionInfo struct {
-	Name    string
-	Version string
-}
-
-func NewUAVersionInfo(name, version string) UAVersionInfo {
-	return UAVersionInfo{
-		Name:    name,
-		Version: version,
-	}
-}
-
-func (vi *UAVersionInfo) isValid() bool {
-	const stopChars = " \t\r\n/"
-	name := vi.Name
-	vers := vi.Version
-	if len(name) == 0 || strings.ContainsAny(name, stopChars) {
-		return false
-	}
-	if len(vers) == 0 || strings.ContainsAny(vers, stopChars) {
-		return false
-	}
-	return true
-}
-
-// Convert versions to a string and append the string to the string base.
-//
-// Each UAVersionInfo will be converted to a string in the format of
-// "product/version", where the "product" is get from the name field, while
-// version is get from the version field. Several pieces of verson information
-// will be concatinated and separated by space.
-func AppendVersions(base string, versions ...UAVersionInfo) string {
-	if len(versions) == 0 {
-		return base
-	}
-
-	verstrs := make([]string, 0, 1+len(versions))
-	if len(base) > 0 {
-		verstrs = append(verstrs, base)
-	}
-
-	for _, v := range versions {
-		if !v.isValid() {
-			continue
-		}
-		verstrs = append(verstrs, v.Name+"/"+v.Version)
-	}
-	return strings.Join(verstrs, " ")
-}
-
-// Decorator is used to change an instance of
-// http.Request. It could be used to add more header fields,
-// change body, etc.
-type Decorator interface {
-	// ChangeRequest() changes the request accordingly.
-	// The changed request will be returned or err will be non-nil
-	// if an error occur.
-	ChangeRequest(req *http.Request) (newReq *http.Request, err error)
-}
-
-// UserAgentDecorator appends the product/version to the user agent field
-// of a request.
-type UserAgentDecorator struct {
-	Versions []UAVersionInfo
-}
-
-func (h *UserAgentDecorator) ChangeRequest(req *http.Request) (*http.Request, error) {
-	if req == nil {
-		return req, ErrNilRequest
-	}
-
-	userAgent := AppendVersions(req.UserAgent(), h.Versions...)
-	if len(userAgent) > 0 {
-		req.Header.Set("User-Agent", userAgent)
-	}
-	return req, nil
-}
-
-type MetaHeadersDecorator struct {
-	Headers map[string][]string
-}
-
-func (h *MetaHeadersDecorator) ChangeRequest(req *http.Request) (*http.Request, error) {
-	if h.Headers == nil {
-		return req, ErrNilRequest
-	}
-	for k, v := range h.Headers {
-		req.Header[k] = v
-	}
-	return req, nil
-}
-
-type AuthDecorator struct {
-	login    string
-	password string
-}
-
-func NewAuthDecorator(login, password string) Decorator {
-	return &AuthDecorator{
-		login:    login,
-		password: password,
-	}
-}
-
-func (self *AuthDecorator) ChangeRequest(req *http.Request) (*http.Request, error) {
-	if req == nil {
-		return req, ErrNilRequest
-	}
-	req.SetBasicAuth(self.login, self.password)
-	return req, nil
-}
-
-// RequestFactory creates an HTTP request
-// and applies a list of decorators on the request.
-type RequestFactory struct {
-	decorators []Decorator
-}
-
-func NewRequestFactory(d ...Decorator) *RequestFactory {
-	return &RequestFactory{
-		decorators: d,
-	}
-}
-
-func (f *RequestFactory) AddDecorator(d ...Decorator) {
-	f.decorators = append(f.decorators, d...)
-}
-
-func (f *RequestFactory) GetDecorators() []Decorator {
-	return f.decorators
-}
-
-// NewRequest() creates a new *http.Request,
-// applies all decorators in the Factory on the request,
-// then applies decorators provided by d on the request.
-func (h *RequestFactory) NewRequest(method, urlStr string, body io.Reader, d ...Decorator) (*http.Request, error) {
-	req, err := http.NewRequest(method, urlStr, body)
-	if err != nil {
-		return nil, err
-	}
-
-	// By default, a nil factory should work.
-	if h == nil {
-		return req, nil
-	}
-	for _, dec := range h.decorators {
-		req, _ = dec.ChangeRequest(req)
-	}
-	for _, dec := range d {
-		req, _ = dec.ChangeRequest(req)
-	}
-	logrus.Debugf("%v -- HEADERS: %v", req.URL, req.Header)
-	return req, err
-}

+ 0 - 222
pkg/requestdecorator/requestdecorator_test.go

@@ -1,222 +0,0 @@
-package requestdecorator
-
-import (
-	"net/http"
-	"strings"
-	"testing"
-)
-
-func TestUAVersionInfo(t *testing.T) {
-	uavi := NewUAVersionInfo("foo", "bar")
-	if !uavi.isValid() {
-		t.Fatalf("UAVersionInfo should be valid")
-	}
-	uavi = NewUAVersionInfo("", "bar")
-	if uavi.isValid() {
-		t.Fatalf("Expected UAVersionInfo to be invalid")
-	}
-	uavi = NewUAVersionInfo("foo", "")
-	if uavi.isValid() {
-		t.Fatalf("Expected UAVersionInfo to be invalid")
-	}
-}
-
-func TestUserAgentDecorator(t *testing.T) {
-	httpVersion := make([]UAVersionInfo, 2)
-	httpVersion = append(httpVersion, NewUAVersionInfo("testname", "testversion"))
-	httpVersion = append(httpVersion, NewUAVersionInfo("name", "version"))
-	uad := &UserAgentDecorator{
-		Versions: httpVersion,
-	}
-
-	req, err := http.NewRequest("GET", "/something", strings.NewReader("test"))
-	if err != nil {
-		t.Fatal(err)
-	}
-	reqDecorated, err := uad.ChangeRequest(req)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	if reqDecorated.Header.Get("User-Agent") != "testname/testversion name/version" {
-		t.Fatalf("Request should have User-Agent 'testname/testversion name/version'")
-	}
-}
-
-func TestUserAgentDecoratorErr(t *testing.T) {
-	httpVersion := make([]UAVersionInfo, 0)
-	uad := &UserAgentDecorator{
-		Versions: httpVersion,
-	}
-
-	var req *http.Request
-	_, err := uad.ChangeRequest(req)
-	if err == nil {
-		t.Fatalf("Expected to get ErrNilRequest instead no error was returned")
-	}
-}
-
-func TestMetaHeadersDecorator(t *testing.T) {
-	var headers = map[string][]string{
-		"key1": {"value1"},
-		"key2": {"value2"},
-	}
-	mhd := &MetaHeadersDecorator{
-		Headers: headers,
-	}
-
-	req, err := http.NewRequest("GET", "/something", strings.NewReader("test"))
-	if err != nil {
-		t.Fatal(err)
-	}
-	reqDecorated, err := mhd.ChangeRequest(req)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	v, ok := reqDecorated.Header["key1"]
-	if !ok {
-		t.Fatalf("Expected to have header key1")
-	}
-	if v[0] != "value1" {
-		t.Fatalf("Expected value for key1 isn't value1")
-	}
-
-	v, ok = reqDecorated.Header["key2"]
-	if !ok {
-		t.Fatalf("Expected to have header key2")
-	}
-	if v[0] != "value2" {
-		t.Fatalf("Expected value for key2 isn't value2")
-	}
-}
-
-func TestMetaHeadersDecoratorErr(t *testing.T) {
-	mhd := &MetaHeadersDecorator{}
-
-	var req *http.Request
-	_, err := mhd.ChangeRequest(req)
-	if err == nil {
-		t.Fatalf("Expected to get ErrNilRequest instead no error was returned")
-	}
-}
-
-func TestAuthDecorator(t *testing.T) {
-	ad := NewAuthDecorator("test", "password")
-
-	req, err := http.NewRequest("GET", "/something", strings.NewReader("test"))
-	if err != nil {
-		t.Fatal(err)
-	}
-	reqDecorated, err := ad.ChangeRequest(req)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	username, password, ok := reqDecorated.BasicAuth()
-	if !ok {
-		t.Fatalf("Cannot retrieve basic auth info from request")
-	}
-	if username != "test" {
-		t.Fatalf("Expected username to be test, got %s", username)
-	}
-	if password != "password" {
-		t.Fatalf("Expected password to be password, got %s", password)
-	}
-}
-
-func TestAuthDecoratorErr(t *testing.T) {
-	ad := &AuthDecorator{}
-
-	var req *http.Request
-	_, err := ad.ChangeRequest(req)
-	if err == nil {
-		t.Fatalf("Expected to get ErrNilRequest instead no error was returned")
-	}
-}
-
-func TestRequestFactory(t *testing.T) {
-	ad := NewAuthDecorator("test", "password")
-	httpVersion := make([]UAVersionInfo, 2)
-	httpVersion = append(httpVersion, NewUAVersionInfo("testname", "testversion"))
-	httpVersion = append(httpVersion, NewUAVersionInfo("name", "version"))
-	uad := &UserAgentDecorator{
-		Versions: httpVersion,
-	}
-
-	requestFactory := NewRequestFactory(ad, uad)
-
-	if l := len(requestFactory.GetDecorators()); l != 2 {
-		t.Fatalf("Expected to have two decorators, got %d", l)
-	}
-
-	req, err := requestFactory.NewRequest("GET", "/test", strings.NewReader("test"))
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	username, password, ok := req.BasicAuth()
-	if !ok {
-		t.Fatalf("Cannot retrieve basic auth info from request")
-	}
-	if username != "test" {
-		t.Fatalf("Expected username to be test, got %s", username)
-	}
-	if password != "password" {
-		t.Fatalf("Expected password to be password, got %s", password)
-	}
-	if req.Header.Get("User-Agent") != "testname/testversion name/version" {
-		t.Fatalf("Request should have User-Agent 'testname/testversion name/version'")
-	}
-}
-
-func TestRequestFactoryNewRequestWithDecorators(t *testing.T) {
-	ad := NewAuthDecorator("test", "password")
-
-	requestFactory := NewRequestFactory(ad)
-
-	if l := len(requestFactory.GetDecorators()); l != 1 {
-		t.Fatalf("Expected to have one decorators, got %d", l)
-	}
-
-	ad2 := NewAuthDecorator("test2", "password2")
-
-	req, err := requestFactory.NewRequest("GET", "/test", strings.NewReader("test"), ad2)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	username, password, ok := req.BasicAuth()
-	if !ok {
-		t.Fatalf("Cannot retrieve basic auth info from request")
-	}
-	if username != "test2" {
-		t.Fatalf("Expected username to be test, got %s", username)
-	}
-	if password != "password2" {
-		t.Fatalf("Expected password to be password, got %s", password)
-	}
-}
-
-func TestRequestFactoryAddDecorator(t *testing.T) {
-	requestFactory := NewRequestFactory()
-
-	if l := len(requestFactory.GetDecorators()); l != 0 {
-		t.Fatalf("Expected to have zero decorators, got %d", l)
-	}
-
-	ad := NewAuthDecorator("test", "password")
-	requestFactory.AddDecorator(ad)
-
-	if l := len(requestFactory.GetDecorators()); l != 1 {
-		t.Fatalf("Expected to have one decorators, got %d", l)
-	}
-}
-
-func TestRequestFactoryNil(t *testing.T) {
-	var requestFactory RequestFactory
-	_, err := requestFactory.NewRequest("GET", "/test", strings.NewReader("test"))
-	if err != nil {
-		t.Fatalf("Expected not to get and error, got %s", err)
-	}
-}

+ 1 - 0
pkg/useragent/README.md

@@ -0,0 +1 @@
+This package provides helper functions to pack version information into a single User-Agent header.

+ 60 - 0
pkg/useragent/useragent.go

@@ -0,0 +1,60 @@
+// Package useragent provides helper functions to pack
+// version information into a single User-Agent header.
+package useragent
+
+import (
+	"errors"
+	"strings"
+)
+
+var (
+	ErrNilRequest = errors.New("request cannot be nil")
+)
+
+// VersionInfo is used to model UserAgent versions.
+type VersionInfo struct {
+	Name    string
+	Version string
+}
+
+func (vi *VersionInfo) isValid() bool {
+	const stopChars = " \t\r\n/"
+	name := vi.Name
+	vers := vi.Version
+	if len(name) == 0 || strings.ContainsAny(name, stopChars) {
+		return false
+	}
+	if len(vers) == 0 || strings.ContainsAny(vers, stopChars) {
+		return false
+	}
+	return true
+}
+
+// Convert versions to a string and append the string to the string base.
+//
+// Each VersionInfo will be converted to a string in the format of
+// "product/version", where the "product" is get from the name field, while
+// version is get from the version field. Several pieces of verson information
+// will be concatinated and separated by space.
+//
+// Example:
+// AppendVersions("base", VersionInfo{"foo", "1.0"}, VersionInfo{"bar", "2.0"})
+// results in "base foo/1.0 bar/2.0".
+func AppendVersions(base string, versions ...VersionInfo) string {
+	if len(versions) == 0 {
+		return base
+	}
+
+	verstrs := make([]string, 0, 1+len(versions))
+	if len(base) > 0 {
+		verstrs = append(verstrs, base)
+	}
+
+	for _, v := range versions {
+		if !v.isValid() {
+			continue
+		}
+		verstrs = append(verstrs, v.Name+"/"+v.Version)
+	}
+	return strings.Join(verstrs, " ")
+}

+ 31 - 0
pkg/useragent/useragent_test.go

@@ -0,0 +1,31 @@
+package useragent
+
+import "testing"
+
+func TestVersionInfo(t *testing.T) {
+	vi := VersionInfo{"foo", "bar"}
+	if !vi.isValid() {
+		t.Fatalf("VersionInfo should be valid")
+	}
+	vi = VersionInfo{"", "bar"}
+	if vi.isValid() {
+		t.Fatalf("Expected VersionInfo to be invalid")
+	}
+	vi = VersionInfo{"foo", ""}
+	if vi.isValid() {
+		t.Fatalf("Expected VersionInfo to be invalid")
+	}
+}
+
+func TestAppendVersions(t *testing.T) {
+	vis := []VersionInfo{
+		{"foo", "1.0"},
+		{"bar", "0.1"},
+		{"pi", "3.1.4"},
+	}
+	v := AppendVersions("base", vis...)
+	expect := "base foo/1.0 bar/0.1 pi/3.1.4"
+	if v != expect {
+		t.Fatalf("expected %q, got %q", expect, v)
+	}
+}

+ 9 - 9
registry/registry.go

@@ -18,8 +18,8 @@ import (
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/docker/autogen/dockerversion"
 	"github.com/docker/docker/pkg/parsers/kernel"
-	"github.com/docker/docker/pkg/requestdecorator"
 	"github.com/docker/docker/pkg/timeoutconn"
+	"github.com/docker/docker/pkg/useragent"
 )
 
 var (
@@ -186,17 +186,17 @@ func cloneRequest(r *http.Request) *http.Request {
 
 func (tr *DockerHeaders) RoundTrip(req *http.Request) (*http.Response, error) {
 	req = cloneRequest(req)
-	httpVersion := make([]requestdecorator.UAVersionInfo, 0, 4)
-	httpVersion = append(httpVersion, requestdecorator.NewUAVersionInfo("docker", dockerversion.VERSION))
-	httpVersion = append(httpVersion, requestdecorator.NewUAVersionInfo("go", runtime.Version()))
-	httpVersion = append(httpVersion, requestdecorator.NewUAVersionInfo("git-commit", dockerversion.GITCOMMIT))
+	httpVersion := make([]useragent.VersionInfo, 0, 4)
+	httpVersion = append(httpVersion, useragent.VersionInfo{"docker", dockerversion.VERSION})
+	httpVersion = append(httpVersion, useragent.VersionInfo{"go", runtime.Version()})
+	httpVersion = append(httpVersion, useragent.VersionInfo{"git-commit", dockerversion.GITCOMMIT})
 	if kernelVersion, err := kernel.GetKernelVersion(); err == nil {
-		httpVersion = append(httpVersion, requestdecorator.NewUAVersionInfo("kernel", kernelVersion.String()))
+		httpVersion = append(httpVersion, useragent.VersionInfo{"kernel", kernelVersion.String()})
 	}
-	httpVersion = append(httpVersion, requestdecorator.NewUAVersionInfo("os", runtime.GOOS))
-	httpVersion = append(httpVersion, requestdecorator.NewUAVersionInfo("arch", runtime.GOARCH))
+	httpVersion = append(httpVersion, useragent.VersionInfo{"os", runtime.GOOS})
+	httpVersion = append(httpVersion, useragent.VersionInfo{"arch", runtime.GOARCH})
 
-	userAgent := requestdecorator.AppendVersions(req.UserAgent(), httpVersion...)
+	userAgent := useragent.AppendVersions(req.UserAgent(), httpVersion...)
 
 	req.Header.Set("User-Agent", userAgent)