diff options
| -rw-r--r-- | cmd/server/hits.go | 2 | ||||
| -rw-r--r-- | counter/sws.js | 2 | ||||
| -rw-r--r-- | hit.go | 25 | ||||
| -rw-r--r-- | sql/sqlite3/02_hits.sql | 13 | ||||
| -rw-r--r-- | store/sqlite3.go | 18 | ||||
| -rw-r--r-- | templates/example.tmpl | 7 | ||||
| -rw-r--r-- | user_agent.go | 33 |
7 files changed, 77 insertions, 23 deletions
diff --git a/cmd/server/hits.go b/cmd/server/hits.go index 54574b1..64bab3b 100644 --- a/cmd/server/hits.go +++ b/cmd/server/hits.go @@ -26,7 +26,7 @@ func handleHitCounter(db sws.CounterStore) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { hit, err := sws.HitFromRequest(r) if err != nil { - log("failed to create hit", err) + log("failed to extract hit", err) http.Error(w, err.Error(), http.StatusBadRequest) return } diff --git a/counter/sws.js b/counter/sws.js index 08c353a..9fabcf2 100644 --- a/counter/sws.js +++ b/counter/sws.js @@ -8,7 +8,7 @@ var me = document.currentScript console.log('me:', me) console.log('me.sws:', me.dataset.sws) -_sws = _sws || {xhr:true} +var _sws = w._sws || {xhr:true} console.log('_sws:', _sws) _sws.d = _sws.d || me.dataset.sws || 'http://sws.userspace.com.au/sws.gif' console.log('using', _sws.d) @@ -19,15 +19,16 @@ type Hit struct { Query *string `json:"query,omitempty"` Fragment *string `json:"fragment,omitempty"` - Title *string `json:"title,omitempty"` - Referrer *string `json:"referrer,omitempty"` - UserAgent *string `json:"user_agent,omitempty"` - ViewPort *string `json:"view_port,omitempty"` + Title *string `json:"title,omitempty"` + Referrer *string `json:"referrer,omitempty"` + UserAgentHash *string `json:"user_agent_hash,omitempty"` + ViewPort *string `json:"view_port,omitempty"` //Features map[string]string `json:"features,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"` // TODO - Domain *Domain `json:"-"` + Domain *Domain `json:"-"` + UserAgent *UserAgent `json:"-"` } func (h Hit) String() string { @@ -92,11 +93,15 @@ func HitFromRequest(r *http.Request) (*Hit, error) { } agent := q.Get("u") - if agent != "" { - out.UserAgent = &agent - } else { - s := r.UserAgent() - out.UserAgent = &s + if agent == "" { + agent = r.UserAgent() + } + uaHash := UserAgentHash(agent) + out.UserAgentHash = &uaHash + out.UserAgent = &UserAgent{ + Hash: uaHash, + Name: agent, + LastSeenAt: time.Now(), } if view := q.Get("v"); view != "" { diff --git a/sql/sqlite3/02_hits.sql b/sql/sqlite3/02_hits.sql index 2fd5539..ca76f0b 100644 --- a/sql/sqlite3/02_hits.sql +++ b/sql/sqlite3/02_hits.sql @@ -1,3 +1,11 @@ +pragma foreign_keys = on; + +create table user_agents ( + hash varchar not null primary key, + name varchar not null, + last_seen_at timestamp not null +); + create table hits ( id integer primary key autoincrement, domain_id integer check(domain_id >0), @@ -8,8 +16,9 @@ create table hits ( query varchar null, title varchar null, referrer varchar null, - user_agent varchar null, + user_agent_hash varchar null, view_port varchar null, - created_at timestamp not null + created_at timestamp not null, + foreign key(user_agent_hash) references user_agents(hash) ); create index "hits#domain_id#created" on hits(domain_id, created_at); diff --git a/store/sqlite3.go b/store/sqlite3.go index fce375a..499e8c5 100644 --- a/store/sqlite3.go +++ b/store/sqlite3.go @@ -74,6 +74,11 @@ func (s *Sqlite3) GetHits(d sws.Domain, start, end time.Time, f map[string]inter } func (s *Sqlite3) SaveHit(h *sws.Hit) error { + if h.UserAgent != nil { + if _, err := s.db.NamedExec(stmts["saveUserAgent"], *h.UserAgent); err != nil { + return err + } + } if _, err := s.db.NamedExec(stmts["saveHit"], h); err != nil { return err } @@ -91,12 +96,19 @@ created_at, updated_at from domains where id = $1 limit 1`, name, description, aliases, enabled, created_at, updated_at) values (:name, :description, :aliases, :enabled, :created_at, :updated_at)`, + "userAgentByHash": `select id, hash, name, last_seen_at from domains +where hash = $1 limit 1`, + + "saveUserAgent": `insert into user_agents (hash, name, last_seen_at) +values (:hash, :name, :last_seen_at) on conflict(hash) do update set +last_seen_at = :last_seen_at`, + "saveHit": `insert into hits ( -domain_id, addr, scheme, host, path, query, title, referrer, user_agent, +domain_id, addr, scheme, host, path, query, title, referrer, user_agent_hash, view_port, created_at) values (:domain_id, :addr, :scheme, :host, :path, :query, -:title, :referrer, :user_agent, :view_port, :created_at)`, +:title, :referrer, :user_agent_hash, :view_port, :created_at)`, "filterHits": `select domain_id, addr, scheme, host, path, title, -referrer, user_agent, view_port, created_at from hits where created_at > :start +referrer, user_agent_hash, view_port, created_at from hits where created_at > :start and created_at < :end`, } diff --git a/templates/example.tmpl b/templates/example.tmpl index 75d28b6..13dd609 100644 --- a/templates/example.tmpl +++ b/templates/example.tmpl @@ -2,12 +2,7 @@ <html> <head> <meta charset="utf-8"> - <script> - var _sws = { - title: "test title" - } - </script> - <script async src="http://localhost:5000/sws.js"></script> + <script async src="http://localhost:5000/sws.js" data-sws="http://localhost:5000/sws.gif"></script> <title>This is the title</title> <noscript> <img src="http://localhost:5000/sws.gif" /> diff --git a/user_agent.go b/user_agent.go new file mode 100644 index 0000000..cbb831b --- /dev/null +++ b/user_agent.go @@ -0,0 +1,33 @@ +package sws + +import ( + "crypto/sha1" + "fmt" + "net/http" + "time" +) + +type UserAgent struct { + Hash string `json:"hash"` + Name string `json:"name"` + LastSeenAt time.Time `json:"last_seen_at"` +} + +func UserAgentHash(s string) string { + return fmt.Sprintf("%x", sha1.Sum([]byte(s))) +} + +func UserAgentFromRequest(r *http.Request) (*UserAgent, error) { + q := r.URL.Query() + agent := q.Get("u") + if agent == "" { + return nil, nil + } + ua := r.UserAgent() + + return &UserAgent{ + Name: ua, + LastSeenAt: time.Now(), + Hash: UserAgentHash(ua), + }, nil +} |
