From 1d0a8966df677c09b4caa429f897cf6d72639129 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 26 Nov 2024 17:14:11 +0000 Subject: [PATCH] Parse user agent into a human-friendly string on submission (#86) I've had to look up UA's far too many times --- changelog.d/86.feature | 1 + go.mod | 1 + go.sum | 5 +++++ submit.go | 10 ++++++++++ submit_test.go | 29 +++++++++++++++++++++++++++-- 5 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 changelog.d/86.feature diff --git a/changelog.d/86.feature b/changelog.d/86.feature new file mode 100644 index 0000000..1e428f9 --- /dev/null +++ b/changelog.d/86.feature @@ -0,0 +1 @@ +Parse User-Agent into a human readable format and attach to the report alongside the raw UA string. \ No newline at end of file diff --git a/go.mod b/go.mod index d422726..31069bd 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.16 require ( github.com/google/go-github v0.0.0-20170401000335-12363ffc1001 github.com/jordan-wright/email v4.0.1-0.20200824153738-3f5bafa1cd84+incompatible + github.com/ua-parser/uap-go v0.0.0-20241012191800-bbb40edc15aa // indirect github.com/xanzy/go-gitlab v0.50.2 golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288 gopkg.in/yaml.v2 v2.2.8 diff --git a/go.sum b/go.sum index 559ce59..92dfd2a 100644 --- a/go.sum +++ b/go.sum @@ -13,6 +13,8 @@ github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxC github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-retryablehttp v0.6.8 h1:92lWxgpa+fF3FozM4B3UZtHZMJX8T5XT+TFdCxsPyWs= github.com/hashicorp/go-retryablehttp v0.6.8/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/jordan-wright/email v4.0.1-0.20200824153738-3f5bafa1cd84+incompatible h1:d60x4RsAHk/UX/0OT8Gc6D7scVvhBbEANpTAWrDhA/I= github.com/jordan-wright/email v4.0.1-0.20200824153738-3f5bafa1cd84+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -21,6 +23,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/ua-parser/uap-go v0.0.0-20241012191800-bbb40edc15aa h1:VzPR4xFM7HARqNocjdHg75ZL9SAgFtaF3P57ZdDcG6I= +github.com/ua-parser/uap-go v0.0.0-20241012191800-bbb40edc15aa/go.mod h1:BUbeWZiieNxAuuADTBNb3/aeje6on3DhU3rpWsQSB1E= github.com/xanzy/go-gitlab v0.50.2 h1:Qm/um2Jryuqusc6VmN7iZYVTQVzNynzSiuMJDnCU1wE= github.com/xanzy/go-gitlab v0.50.2/go.mod h1:Q+hQhV508bDPoBijv7YjK/Lvlb4PhVhJdKqXVQrUoAE= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -45,6 +49,7 @@ google.golang.org/appengine v1.3.0 h1:FBSsiFRMz3LBeXIomRnVzrQwSDj4ibvcRexLG0LZGQ google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/submit.go b/submit.go index 746b7f7..1ef5c6a 100644 --- a/submit.go +++ b/submit.go @@ -23,6 +23,7 @@ import ( "encoding/base32" "encoding/json" "fmt" + "github.com/ua-parser/uap-go/uaparser" "io" "io/ioutil" "log" @@ -291,6 +292,13 @@ func parseRequest(w http.ResponseWriter, req *http.Request, reportDir string) *p return p } +var uaParser *uaparser.Parser = uaparser.NewFromSaved() + +func parseUserAgent(userAgent string) string { + client := uaParser.Parse(userAgent) + return fmt.Sprintf(`%s on %s running on %s device`, client.UserAgent.ToString(), client.Os.ToString(), client.Device.ToString()) +} + func parseJSONRequest(w http.ResponseWriter, req *http.Request, reportDir string) (*payload, error) { var p jsonPayload if err := json.NewDecoder(req.Body).Decode(&p); err != nil { @@ -321,6 +329,7 @@ func parseJSONRequest(w http.ResponseWriter, req *http.Request, reportDir string parsed.AppName = p.AppName if p.UserAgent != "" { + parsed.Data["Parsed-User-Agent"] = parseUserAgent(p.UserAgent) parsed.Data["User-Agent"] = p.UserAgent } if p.Version != "" { @@ -425,6 +434,7 @@ func formPartToPayload(field, data string, p *payload) { p.Data["Version"] = data } else if field == "user_agent" { p.Data["User-Agent"] = data + p.Data["Parsed-User-Agent"] = parseUserAgent(data) } else if field == "label" { p.Labels = append(p.Labels, data) } else { diff --git a/submit_test.go b/submit_test.go index 12ebefe..6b9d464 100644 --- a/submit_test.go +++ b/submit_test.go @@ -259,8 +259,9 @@ func checkParsedMultipartUpload(t *testing.T, p *payload) { if len(p.Logs) != 4 { t.Errorf("Log length: got %d, want 4", len(p.Logs)) } - if len(p.Data) != 3 { - t.Errorf("Data length: got %d, want 3", len(p.Data)) + // One extra data field to account for User Agent being parsed into two fields + if len(p.Data) != 4 { + t.Errorf("Data length: got %d, want 4", len(p.Data)) } if len(p.Labels) != 0 { t.Errorf("Labels: got %#v, want []", p.Labels) @@ -588,3 +589,27 @@ user_id: id } } } + +func TestParseUserAgent(t *testing.T) { + reportDir := mkTempDir(t) + defer os.RemoveAll(reportDir) + + body := `{ + "app": "riot-web", + "logs": [], + "text": "test message", + "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.6723.91 Safari/537.3", + "version": "0.9.9" +}` + + p, _ := testParsePayload(t, body, "application/json", reportDir) + + if p == nil { + t.Fatal("parseRequest returned nil") + } + + wanted := "Chrome 130.0.6723 on Windows 10 running on Other device" + if p.Data["Parsed-User-Agent"] != wanted { + t.Errorf("user agent: got %s, want %s", p.Data["Parsed-User-Agent"], wanted) + } +}