Skip to content

Commit 14a2d64

Browse files
committed
origins: extract host and forwarder information
1 parent e2624ed commit 14a2d64

2 files changed

Lines changed: 82 additions & 0 deletions

File tree

useragent.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
// Origin contins request origination context from parsing request headers.
1212
type Origin struct {
1313
Method string
14+
Host string
15+
Forward string
1416
Reference string
1517
UserAgent useragent.UserAgent
1618
}
@@ -48,15 +50,22 @@ func (o *Origin) String() string {
4850
// Origins parses the request headers to get information about the origins of
4951
// the request, including ...
5052
//
53+
// - Method
54+
// - Host
55+
// - Forwarder
5156
// - Referer
5257
// - User-Agent
5358
func Origins(r *http.Request) *Origin {
5459
method := strings.ToUpper(r.Method)
60+
host := r.Host
61+
forward := r.Header.Get("X-Forwarded-For")
5562
reference := r.Header.Get("Referer")
5663
agent := r.Header.Get("User-Agent")
5764
ua := useragent.Parse(agent)
5865
return &Origin{
5966
Method: method,
67+
Host: host,
68+
Forward: forward,
6069
Reference: reference,
6170
UserAgent: ua,
6271
}

useragent_test.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package webtools
2+
3+
import (
4+
"net/http"
5+
"net/http/httptest"
6+
"testing"
7+
8+
"github.com/mileusna/useragent"
9+
"github.com/shoenig/test/must"
10+
)
11+
12+
func TestOrigin_From(t *testing.T) {
13+
t.Parallel()
14+
15+
cases := []struct {
16+
name string
17+
reference string
18+
exp string
19+
}{
20+
{"Empty reference", "", "-"},
21+
{"Standard URL", "https://example.com/path/to/page", "example.com/path/to/page"},
22+
{"URL with query", "http://google.com/search?q=golang", "google.com/search"},
23+
{"URL with fragment", "https://github.com/mileusna/useragent#readme", "github.com/mileusna/useragent"},
24+
}
25+
26+
for _, tc := range cases {
27+
t.Run(tc.name, func(t *testing.T) {
28+
o := &Origin{Reference: tc.reference}
29+
must.Eq(t, tc.exp, o.From())
30+
})
31+
}
32+
}
33+
34+
func TestOrigin_String(t *testing.T) {
35+
t.Parallel()
36+
37+
cases := []struct {
38+
name string
39+
userAgent useragent.UserAgent
40+
want string
41+
}{
42+
{"Bot", useragent.UserAgent{Name: "Googlebot", Bot: true}, "Googlebot/bot"},
43+
{"Mobile", useragent.UserAgent{Name: "Safari", Mobile: true}, "Safari/phone"},
44+
{"Tablet", useragent.UserAgent{Name: "Chrome", Tablet: true}, "Chrome/tablet"},
45+
{"Desktop", useragent.UserAgent{Name: "Firefox", Desktop: true}, "Firefox/desktop"},
46+
{"Unknown", useragent.UserAgent{Name: "MyBrowser"}, "MyBrowser/unknown"},
47+
}
48+
49+
for _, tc := range cases {
50+
t.Run(tc.name, func(t *testing.T) {
51+
o := &Origin{UserAgent: tc.userAgent}
52+
must.Eq(t, tc.want, o.String())
53+
})
54+
}
55+
}
56+
57+
func TestOrigins(t *testing.T) {
58+
t.Parallel()
59+
60+
agent := "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"
61+
r := httptest.NewRequest(http.MethodPost, "https://example.org/v1/data", nil)
62+
r.Header.Set("X-Forwarded-For", "10.1.1.1")
63+
r.Header.Set("Referer", "https://dashboard.example.org/home")
64+
r.Header.Set("User-Agent", agent)
65+
66+
origin := Origins(r)
67+
68+
must.Eq(t, "POST", origin.Method)
69+
must.Eq(t, "example.org", origin.Host)
70+
must.Eq(t, "10.1.1.1", origin.Forward)
71+
must.Eq(t, "https://dashboard.example.org/home", origin.Reference)
72+
must.Eq(t, "Chrome", origin.UserAgent.Name)
73+
}

0 commit comments

Comments
 (0)