diff --git a/pkg/httputils/httputils.go b/pkg/httputils/httputils.go index c586c0232e..0fd90ea3b1 100644 --- a/pkg/httputils/httputils.go +++ b/pkg/httputils/httputils.go @@ -5,11 +5,15 @@ import ( "fmt" "net/http" "regexp" - "strings" "github.com/docker/docker/pkg/jsonmessage" ) +var ( + headerRegexp = regexp.MustCompile(`^(?:(.+)/(.+))\s\((.+)\).*$`) + errInvalidHeader = errors.New("Bad header, should be in format `docker/version (platform)`") +) + // Download requests a given URL and returns an io.Reader. func Download(url string) (resp *http.Response, err error) { if resp, err = http.Get(url); err != nil { @@ -39,21 +43,13 @@ type ServerHeader struct { // ParseServerHeader extracts pieces from an HTTP server header // which is in the format "docker/version (os)" eg docker/1.8.0-dev (windows). func ParseServerHeader(hdr string) (*ServerHeader, error) { - re := regexp.MustCompile(`.*\((.+)\).*$`) - r := &ServerHeader{} - if matches := re.FindStringSubmatch(hdr); matches != nil { - r.OS = matches[1] - parts := strings.Split(hdr, "/") - if len(parts) != 2 { - return nil, errors.New("Bad header: '/' missing") - } - r.App = parts[0] - v := strings.Split(parts[1], " ") - if len(v) != 2 { - return nil, errors.New("Bad header: Expected single space") - } - r.Ver = v[0] - return r, nil + matches := headerRegexp.FindStringSubmatch(hdr) + if len(matches) != 4 { + return nil, errInvalidHeader } - return nil, errors.New("Bad header: Failed regex match") + return &ServerHeader{ + App: matches[1], + Ver: matches[2], + OS: matches[3], + }, nil } diff --git a/pkg/httputils/httputils_test.go b/pkg/httputils/httputils_test.go new file mode 100644 index 0000000000..61e98ba0b4 --- /dev/null +++ b/pkg/httputils/httputils_test.go @@ -0,0 +1,59 @@ +package httputils + +import "testing" + +func TestDownload(t *testing.T) { + _, err := Download("http://docker.com") + + if err != nil { + t.Fatalf("Expected error to not exist when Download(http://docker.com)") + } + + // Expected status code = 404 + if _, err = Download("http://docker.com/abc1234567"); err == nil { + t.Fatalf("Expected error to exist when Download(http://docker.com/abc1234567)") + } +} + +func TestNewHTTPRequestError(t *testing.T) { + errorMessage := "Some error message" + httpResponse, _ := Download("http://docker.com") + if err := NewHTTPRequestError(errorMessage, httpResponse); err.Error() != errorMessage { + t.Fatalf("Expected err to equal error Message") + } +} + +func TestParseServerHeader(t *testing.T) { + if _, err := ParseServerHeader("bad header"); err != errInvalidHeader { + t.Fatalf("Should fail when header can not be parsed") + } + + if _, err := ParseServerHeader("(bad header)"); err != errInvalidHeader { + t.Fatalf("Should fail when header can not be parsed") + } + + if _, err := ParseServerHeader("(without/spaces)"); err != errInvalidHeader { + t.Fatalf("Should fail when header can not be parsed") + } + + if _, err := ParseServerHeader("(header/with space)"); err != errInvalidHeader { + t.Fatalf("Expected err to not exist when ParseServerHeader(\"(header/with space)\")") + } + + serverHeader, err := ParseServerHeader("foo/bar (baz)") + if err != nil { + t.Fatal(err) + } + + if serverHeader.App != "foo" { + t.Fatalf("Expected serverHeader.App to equal \"foo\", got %s", serverHeader.App) + } + + if serverHeader.Ver != "bar" { + t.Fatalf("Expected serverHeader.Ver to equal \"bar\", got %s", serverHeader.Ver) + } + + if serverHeader.OS != "baz" { + t.Fatalf("Expected serverHeader.OS to equal \"baz\", got %s", serverHeader.OS) + } +} diff --git a/pkg/httputils/mimetype_test.go b/pkg/httputils/mimetype_test.go new file mode 100644 index 0000000000..9de433ee8c --- /dev/null +++ b/pkg/httputils/mimetype_test.go @@ -0,0 +1,13 @@ +package httputils + +import ( + "testing" +) + +func TestDetectContentType(t *testing.T) { + input := []byte("That is just a plain text") + + if contentType, _, err := DetectContentType(input); err != nil || contentType != "text/plain" { + t.Errorf("TestDetectContentType failed") + } +}