beacon-store.py (2960B)
1 """ 2 Event beacon store server. 3 4 - When a request body is specified, stores the data in the body for the 'type' 5 specified in the query parameters and serves a 200 response without body. 6 - When a request body is not specified and the request is not served with an 7 'expected_body' parameter, stores an empty body for the 'type' specified in 8 the query parameters and serves a 200 response without body. 9 - When a request body is not specified and the request is served with an 10 'expected_body' parameter, serves a 200 response whose body contains the 11 stored value from the automatic beacon. Since the data is stored using a hash 12 of the data as the key, it uses the `expected_body` query parameter to know 13 what key to look up. If the stored value doesn't exist, serves a 200 response 14 with an empty body. 15 """ 16 import uuid 17 import hashlib 18 19 NO_DATA_STRING = b"<No data>" 20 NOT_SET_STRING = b"<Not set>" 21 22 # The server stash requires a uuid to store data. Use a hash of the automatic 23 # beacon data as the uuid to store and retrieve the data. 24 def string_to_uuid(input): 25 hash_value = hashlib.md5(str(input).encode("UTF-8")).hexdigest() 26 return str(uuid.UUID(hex=hash_value)) 27 28 def main(request, response): 29 stash = request.server.stash; 30 event_type = request.GET.first(b"type", NO_DATA_STRING) 31 32 # The stash is accessed concurrently by many clients. A lock is used to 33 # avoid interleaved read/write from different clients. 34 with stash.lock: 35 # GET requests with an 'expected_body' parameter imply they were sent as 36 # the request from nextBeacon(). 37 if request.method == "GET" and b"expected_body" in request.GET: 38 expected_body = request.GET.first(b"expected_body", NO_DATA_STRING) 39 data = stash.take(string_to_uuid(event_type + expected_body)) or NOT_SET_STRING 40 return (200, [], data) 41 42 # Requests with a body imply they were sent as a reporting beacon 43 # (either through reportEvent() or through an automatic beacon). 44 if request.method == "POST" and event_type: 45 request_body = request.body or NO_DATA_STRING 46 request_origin = request.headers.get("Origin") or NO_DATA_STRING 47 request_referrer = request.headers.get("Referer") or NO_DATA_STRING 48 stash.put(string_to_uuid(event_type + request_body), 49 (request_origin + b"," + request_referrer)) 50 return (200, [], b"") 51 # GET requests without an 'expected_body' parameter imply they were sent 52 # as a destination URL reporting beacon. 53 if request.method == "GET" and event_type: 54 request_origin = request.headers.get("Origin") or NO_DATA_STRING 55 request_referrer = request.headers.get("Referer") or NO_DATA_STRING 56 stash.put(string_to_uuid(event_type + NO_DATA_STRING), 57 (request_origin + b"," + request_referrer)) 58 return (200, [], b"") 59 60 return (400, [], u"")