github.com/portworx/docker@v1.12.1/dockerversion/useragent.go (about) 1 package dockerversion 2 3 import ( 4 "fmt" 5 "runtime" 6 7 "github.com/docker/docker/api/server/httputils" 8 "github.com/docker/docker/pkg/parsers/kernel" 9 "github.com/docker/docker/pkg/useragent" 10 "golang.org/x/net/context" 11 ) 12 13 // DockerUserAgent is the User-Agent the Docker client uses to identify itself. 14 // In accordance with RFC 7231 (5.5.3) is of the form: 15 // [docker client's UA] UpstreamClient([upstream client's UA]) 16 func DockerUserAgent(ctx context.Context) string { 17 httpVersion := make([]useragent.VersionInfo, 0, 6) 18 httpVersion = append(httpVersion, useragent.VersionInfo{Name: "docker", Version: Version}) 19 httpVersion = append(httpVersion, useragent.VersionInfo{Name: "go", Version: runtime.Version()}) 20 httpVersion = append(httpVersion, useragent.VersionInfo{Name: "git-commit", Version: GitCommit}) 21 if kernelVersion, err := kernel.GetKernelVersion(); err == nil { 22 httpVersion = append(httpVersion, useragent.VersionInfo{Name: "kernel", Version: kernelVersion.String()}) 23 } 24 httpVersion = append(httpVersion, useragent.VersionInfo{Name: "os", Version: runtime.GOOS}) 25 httpVersion = append(httpVersion, useragent.VersionInfo{Name: "arch", Version: runtime.GOARCH}) 26 27 dockerUA := useragent.AppendVersions("", httpVersion...) 28 upstreamUA := getUserAgentFromContext(ctx) 29 if len(upstreamUA) > 0 { 30 ret := insertUpstreamUserAgent(upstreamUA, dockerUA) 31 return ret 32 } 33 return dockerUA 34 } 35 36 // getUserAgentFromContext returns the previously saved user-agent context stored in ctx, if one exists 37 func getUserAgentFromContext(ctx context.Context) string { 38 var upstreamUA string 39 if ctx != nil { 40 var ki interface{} = ctx.Value(httputils.UAStringKey) 41 if ki != nil { 42 upstreamUA = ctx.Value(httputils.UAStringKey).(string) 43 } 44 } 45 return upstreamUA 46 } 47 48 // escapeStr returns s with every rune in charsToEscape escaped by a backslash 49 func escapeStr(s string, charsToEscape string) string { 50 var ret string 51 for _, currRune := range s { 52 appended := false 53 for _, escapeableRune := range charsToEscape { 54 if currRune == escapeableRune { 55 ret += `\` + string(currRune) 56 appended = true 57 break 58 } 59 } 60 if !appended { 61 ret += string(currRune) 62 } 63 } 64 return ret 65 } 66 67 // insertUpstreamUserAgent adds the upstream client useragent to create a user-agent 68 // string of the form: 69 // $dockerUA UpstreamClient($upstreamUA) 70 func insertUpstreamUserAgent(upstreamUA string, dockerUA string) string { 71 charsToEscape := `();\` 72 upstreamUAEscaped := escapeStr(upstreamUA, charsToEscape) 73 return fmt.Sprintf("%s UpstreamClient(%s)", dockerUA, upstreamUAEscaped) 74 }