github.com/olljanat/moby@v1.13.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  }