60 lines
2.9 KiB
Python
60 lines
2.9 KiB
Python
"""
|
|
Event beacon store server.
|
|
|
|
- When a request body is specified, stores the data in the body for the 'type'
|
|
specified in the query parameters and serves a 200 response without body.
|
|
- When a request body is not specified and the request is not served with an
|
|
'expected_body' parameter, stores an empty body for the 'type' specified in
|
|
the query parameters and serves a 200 response without body.
|
|
- When a request body is not specified and the request is served with an
|
|
'expected_body' parameter, serves a 200 response whose body contains the
|
|
stored value from the automatic beacon. Since the data is stored using a hash
|
|
of the data as the key, it uses the `expected_body` query parameter to know
|
|
what key to look up. If the stored value doesn't exist, serves a 200 response
|
|
with an empty body.
|
|
"""
|
|
import uuid
|
|
import hashlib
|
|
|
|
NO_DATA_STRING = b"<No data>"
|
|
NOT_SET_STRING = b"<Not set>"
|
|
|
|
# The server stash requires a uuid to store data. Use a hash of the automatic
|
|
# beacon data as the uuid to store and retrieve the data.
|
|
def string_to_uuid(input):
|
|
hash_value = hashlib.md5(str(input).encode("UTF-8")).hexdigest()
|
|
return str(uuid.UUID(hex=hash_value))
|
|
|
|
def main(request, response):
|
|
stash = request.server.stash;
|
|
event_type = request.GET.first(b"type", NO_DATA_STRING)
|
|
|
|
# The stash is accessed concurrently by many clients. A lock is used to
|
|
# avoid interleaved read/write from different clients.
|
|
with stash.lock:
|
|
# GET requests with an 'expected_body' parameter imply they were sent as
|
|
# the request from nextBeacon().
|
|
if request.method == "GET" and b"expected_body" in request.GET:
|
|
expected_body = request.GET.first(b"expected_body", NO_DATA_STRING)
|
|
data = stash.take(string_to_uuid(event_type + expected_body)) or NOT_SET_STRING
|
|
return (200, [], data)
|
|
|
|
# Requests with a body imply they were sent as a reporting beacon
|
|
# (either through reportEvent() or through an automatic beacon).
|
|
if request.method == "POST" and event_type:
|
|
request_body = request.body or NO_DATA_STRING
|
|
request_origin = request.headers.get("Origin") or NO_DATA_STRING
|
|
request_referrer = request.headers.get("Referer") or NO_DATA_STRING
|
|
stash.put(string_to_uuid(event_type + request_body),
|
|
(request_origin + b"," + request_referrer))
|
|
return (200, [], b"")
|
|
# GET requests without an 'expected_body' parameter imply they were sent
|
|
# as a destination URL reporting beacon.
|
|
if request.method == "GET" and event_type:
|
|
request_origin = request.headers.get("Origin") or NO_DATA_STRING
|
|
request_referrer = request.headers.get("Referer") or NO_DATA_STRING
|
|
stash.put(string_to_uuid(event_type + NO_DATA_STRING),
|
|
(request_origin + b"," + request_referrer))
|
|
return (200, [], b"")
|
|
|
|
return (400, [], u"")
|