Skip to content

Commit

Permalink
Merge pull request #93 from kim-tsao/client-header
Browse files Browse the repository at this point in the history
registry option updates
  • Loading branch information
kim-tsao authored Nov 25, 2021
2 parents 72dfe15 + 69cc018 commit d7edf14
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 33 deletions.
9 changes: 6 additions & 3 deletions index/server/pkg/server/endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ func serveDevfile(c *gin.Context) {
// Track event for telemetry
if enableTelemetry {
user := util.GetUser(c)
client := util.GetClient(c)

err := util.TrackEvent(analytics.Track{
Event: eventTrackMap["view"],
Expand All @@ -117,7 +118,8 @@ func serveDevfile(c *gin.Context) {
Properties: analytics.NewProperties().
Set("name", name).
Set("type", string(devfileIndex.Type)).
Set("registry", registry),
Set("registry", registry).
Set("client", client),
})
if err != nil {
log.Println(err)
Expand Down Expand Up @@ -236,14 +238,15 @@ func buildIndexAPIResponse(c *gin.Context) {
// Track event for telemetry
if enableTelemetry {
user := util.GetUser(c)

client := util.GetClient(c)
err := util.TrackEvent(analytics.Track{
Event: eventTrackMap["list"],
UserId: user,
Context: util.SetContext(c),
Properties: analytics.NewProperties().
Set("type", indexType).
Set("registry", registry),
Set("registry", registry).
Set("client", client),
})
if err != nil {
log.Println(err)
Expand Down
4 changes: 3 additions & 1 deletion index/server/pkg/server/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,16 @@ func ociServerProxy(c *gin.Context) {

if resource == "blobs" {
user := util.GetUser(c)
client := util.GetClient(c)

err := util.TrackEvent(analytics.Track{
Event: eventTrackMap["download"],
UserId: user,
Context: util.SetContext(c),
Properties: analytics.NewProperties().
Set("name", name).
Set("registry", registry),
Set("registry", registry).
Set("client", client),
})
if err != nil {
log.Println(err.Error())
Expand Down
57 changes: 37 additions & 20 deletions index/server/pkg/util/telemetry.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (

const (
telemetryKey = "6HBMiy5UxBtsbxXx7O4n0t0u4dt8IAR3"
defaultUser = "anonymous"
defaultUser = "devfile-registry"
)

//TrackEvent tracks event for telemetry
Expand All @@ -28,13 +28,24 @@ func TrackEvent(event analytics.Message) error {

//GetUser gets the user
func GetUser(c *gin.Context) string {
user := defaultUser
user := GetClient(c)
if len(c.Request.Header["User"]) != 0 {
user = c.Request.Header["User"][0]
}
return user
}

func GetClient(c *gin.Context) string {
client := defaultUser

cHeader := c.Request.Header["Client"]
if len(cHeader) != 0 {
client = cHeader[0]
}

return client
}

//SetContext suppresses the collection of IP addresses in Segment but infers the country code from the HTTP `Accept-Language` header
func SetContext(c *gin.Context) *analytics.Context {
aContext := analytics.Context{}
Expand All @@ -45,34 +56,40 @@ func SetContext(c *gin.Context) *analytics.Context {
return &aContext
}

//GetRegion returns the region that's set in Accept-Language header. If the header is unset or can't be determined, an empty string will be returned.
// getRegion returns the region that's set in Accept-Language header if request is coming from a browser or the Locale header if the request is from a client.
// If the header is unset or can't be determined, an empty string will be returned.
func getRegion(c *gin.Context) string {
userPrefs := c.Request.Header["Accept-Language"]
defaultRegion := ""

if len(userPrefs) != 0 {
tags, _, err := language.ParseAcceptLanguage(userPrefs[0])
if err != nil {
log.Println(err.Error() + ", returning an empty string for region")
if len(userPrefs) == 0 {
userPrefs = c.Request.Header["Locale"]
if len(userPrefs) == 0 {
log.Println("The Accept-Language or Locale headers are unset , returning an empty string for region")
return defaultRegion
}
}

if len(tags) > 0 {
//tags are returned in order of precedence, so we can assume the first one is preferred
region, _ := tags[0].Region()
tags, _, err := language.ParseAcceptLanguage(userPrefs[0])
if err != nil {
log.Println(err.Error() + ", returning an empty string for region")
return defaultRegion
}

//if region is undetermined, return the default region
if region.String() == "ZZ" {
log.Println("Region is undetermined, returning an empty string for region")
return defaultRegion
}
if len(tags) > 0 {
//tags are returned in order of precedence, so we can assume the first one is preferred
region, _ := tags[0].Region()

return region.String()
//if region is undetermined, return the default region
if region.String() == "ZZ" {
log.Println("Region is undetermined, returning an empty string for region")
return defaultRegion
}
}

//Accept-Language is not set, empty region
log.Println("Accept-Language header is empty, returning an empty string for region")
return defaultRegion
return region.String()
} else {
log.Println("Locale is unset, returning an empty string for region")
return defaultRegion
}

}
61 changes: 61 additions & 0 deletions index/server/pkg/util/telemetry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"testing"
)

//TestGetUser also tests GetClient indirectly
func TestGetUser(t *testing.T) {
tests := []struct {
name string
Expand All @@ -36,6 +37,17 @@ func TestGetUser(t *testing.T) {
},
want: defaultUser,
},
{
name: "User header is unset, client is set",
context: &gin.Context{
Request: &http.Request{
Header: http.Header{
"Client": {"testclient"},
},
},
},
want: "testclient",
},
{
name: "Multiple users set",
context: &gin.Context{
Expand Down Expand Up @@ -159,6 +171,55 @@ func TestSetContext(t *testing.T) {
IP: net.IPv4(0, 0, 0, 0),
},
},
{
name: "Accept-Language is unset, valid locale is set",
context: &gin.Context{
Request: &http.Request{
Header: http.Header{
"Locale": {"de_DE"},
},
},
},
want: &analytics.Context{
Location: analytics.LocationInfo{
Country: "DE",
},
IP: net.IPv4(0, 0, 0, 0),
},
},
{
name: "Accept-Language is unset, invalid locale is set",
context: &gin.Context{
Request: &http.Request{
Header: http.Header{
"Locale": {"invalid"},
},
},
},
want: &analytics.Context{
Location: analytics.LocationInfo{
Country: "",
},
IP: net.IPv4(0, 0, 0, 0),
},
},
{
name: "Accept-Language and Locale are set",
context: &gin.Context{
Request: &http.Request{
Header: http.Header{
"Accept-Language": {"en_FR"},
"Locale": {"de_DE"},
},
},
},
want: &analytics.Context{
Location: analytics.LocationInfo{
Country: "FR",
},
IP: net.IPv4(0, 0, 0, 0),
},
},
}

for _, test := range tests {
Expand Down
8 changes: 6 additions & 2 deletions registry-library/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,9 @@ func init() {
var err error

options := library.RegistryOptions{
User: user,
Telemetry: library.TelemetryData{
User: "user",
},
SkipTLSVerify: skipTLSVerify,
}

Expand Down Expand Up @@ -117,7 +119,9 @@ func init() {
}

options := library.RegistryOptions{
User: user,
Telemetry: library.TelemetryData{
User: "user",
},
SkipTLSVerify: skipTLSVerify,
}

Expand Down
37 changes: 30 additions & 7 deletions registry-library/library/library.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,19 @@ type Registry struct {
err error
}

//TelemetryData structure to pass in client telemetry information
type TelemetryData struct {
// The User and Locale fields will be passed in by the clients if telemetry opt-in is enabled
User string
Locale string
// the generic client name will be passed in regardless of opt-in/out choice. The value
// will be assigned to the UserId field for opt-outs
Client string
}

type RegistryOptions struct {
SkipTLSVerify bool
User string
Telemetry TelemetryData
Filter RegistryFilter
}

Expand Down Expand Up @@ -127,9 +137,9 @@ func GetRegistryIndex(registryURL string, options RegistryOptions, devfileTypes
if err != nil {
return nil, err
}
if options.User != "" {
req.Header.Add("User", options.User)
}

setHeaders(&req.Header, options)

httpClient := &http.Client{
Transport: &http.Transport{
ResponseHeaderTimeout: responseHeaderTimeout,
Expand Down Expand Up @@ -238,9 +248,8 @@ func PullStackByMediaTypesFromRegistry(registry string, stack string, allowedMed
},
}
headers := make(http.Header)
if options.User != "" {
headers.Add("User", options.User)
}
setHeaders(&headers, options)

resolver := docker.NewResolver(docker.ResolverOptions{Headers: headers, PlainHTTP: plainHTTP, Client: httpClient})
ref := path.Join(urlObj.Host, stackIndex.Links["self"])
fileStore := content.NewFileStore(destDir)
Expand Down Expand Up @@ -321,3 +330,17 @@ func decompress(targetDir string, tarFile string) error {

return nil
}

//setHeaders sets the request headers
func setHeaders(headers *http.Header, options RegistryOptions) {
t := options.Telemetry
if t.User != "" {
headers.Add("User", t.User)
}
if t.Client != "" {
headers.Add("Client", t.Client)
}
if t.Locale != "" {
headers.Add("Locale", t.Locale)
}
}

0 comments on commit d7edf14

Please sign in to comment.