-
Notifications
You must be signed in to change notification settings - Fork 6
/
flask_analytics.py
94 lines (77 loc) · 2.9 KB
/
flask_analytics.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
from __future__ import absolute_import
from datetime import datetime, timedelta
from hashlib import sha1
from urlparse import urlparse
from uuid import uuid4
import hmac
from flask import _request_ctx_stack, current_app, session
COOKIE_NAME = 'analytics'
COOKIE_DURATION = timedelta(days=365)
def _cookie_digest(payload, key=None):
if key is None:
key = current_app.config["SECRET_KEY"]
payload = payload.encode("utf8")
mac = hmac.new(key, payload, sha1)
return mac.hexdigest()
def _get_cookie(request):
config = current_app.config
cookie_name = config.get("ANALYTICS_COOKIE_NAME", COOKIE_NAME)
request_cookie = request.headers['cookie']
cookies = request_cookie.split(';')
for cookie_data in cookies:
if cookie_name in cookie_data:
name, value = cookie_data.split('=')
return value
return None
class Analytics(object):
analytics_callback = None
def __init__(self, app):
self.app = app
self.cookie_value = None
if self.app:
self.init_app(app)
def init_app(self, app):
self.app = app
if not hasattr(app, 'extensions'):
app.extensions = {}
app.extensions['analytics'] = self
app.before_request(self.before_request)
app.after_request(self.after_request)
def analytics_process(self, callback):
self.analytics_callback = callback
def before_request(self):
ctx = _request_ctx_stack.top
cookie_value = _get_cookie(ctx.request)
if cookie_value:
self.cookie_value = cookie_value
self.track_request(ctx.request)
def after_request(self, response):
config = current_app.config
cookie_name = config.get("ANALYTICS_COOKIE_NAME", COOKIE_NAME)
self._set_tracker(response)
return response
def _set_tracker(self, response):
if self.cookie_value:
return
config = current_app.config
name = config.get("ANALYTICS_COOKIE_NAME", COOKIE_NAME)
domain = config.get("ANALYTICS_COOKIE_DOMAIN", None)
duration = config.get("ANALYTICS_COOKIE_DURATION", COOKIE_DURATION)
data = _cookie_digest(str(uuid4()))
expires = datetime.now() + duration
response.set_cookie(name, data, expires=expires, domain=domain)
def track_request(self, request):
parse_result = urlparse(request.url)
static_url_path = current_app.static_url_path
analytics = {
'args': request.args,
'charset': request.url_charset,
'url': request.url,
'user_agent': request.user_agent,
'cookie': self.cookie_value,
'is_static': parse_result.path.startswith(static_url_path),
'blueprint': request.blueprint,
'view_args': request.view_args,
'remote_addr': request.remote_addr,
}
self.analytics_callback(analytics)