diff options
Diffstat (limited to 'testing/web-platform/tests/beacon/resources/beacon.py')
-rw-r--r-- | testing/web-platform/tests/beacon/resources/beacon.py | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/testing/web-platform/tests/beacon/resources/beacon.py b/testing/web-platform/tests/beacon/resources/beacon.py new file mode 100644 index 0000000000..d81bfb1ac6 --- /dev/null +++ b/testing/web-platform/tests/beacon/resources/beacon.py @@ -0,0 +1,118 @@ +import json + +from wptserve.utils import isomorphic_decode + +def main(request, response): + """Helper handler for Beacon tests. + + It handles two forms of requests: + + STORE: + A URL with a query string of the form 'cmd=store&id=<token>'. + + Stores the receipt of a sendBeacon() request along with its validation + result, returning HTTP 200 OK. + + if "preflightExpected" exists in the query, this handler responds to + CORS preflights. + + STAT: + A URL with a query string of the form 'cmd=stat&id=<token>'. + + Retrieves the results of test for the given id and returns them as a + JSON array and HTTP 200 OK status code. Due to the eventual read-once + nature of the stash, results for a given test are only guaranteed to be + returned once, though they may be returned multiple times. + + An entry may contain following members. + - error: An error string. null if there is no error. + - type: The content-type header of the request "(missing)" if there + is no content-type header in the request. + + Example response bodies: + - [{error: null, type: "text/plain;charset=UTF8"}] + - [{error: "some validation details"}] + - [] + + Common parameters: + cmd - the command, 'store' or 'stat'. + id - the unique identifier of the test. + """ + + id = request.GET.first(b"id") + command = request.GET.first(b"cmd").lower() + + # Append CORS headers if needed. + if b"origin" in request.GET: + response.headers.set(b"Access-Control-Allow-Origin", + request.GET.first(b"origin")) + if b"credentials" in request.GET: + response.headers.set(b"Access-Control-Allow-Credentials", + request.GET.first(b"credentials")) + + # Handle the 'store' and 'stat' commands. + if command == b"store": + error = None + + # Only store the actual POST requests, not any preflight/OPTIONS + # requests we may get. + if request.method == u"POST": + payload = b"" + contentType = request.headers[b"Content-Type"] \ + if b"Content-Type" in request.headers else b"(missing)" + if b"form-data" in contentType: + if b"payload" in request.POST: + # The payload was sent as a FormData. + payload = request.POST.first(b"payload") + else: + # A FormData was sent with an empty payload. + pass + else: + # The payload was sent as either a string, Blob, or BufferSource. + payload = request.body + + payload_parts = list(filter(None, payload.split(b":"))) + if len(payload_parts) > 0: + payload_size = int(payload_parts[0]) + + # Confirm the payload size sent matches with the number of + # characters sent. + if payload_size != len(payload): + error = u"expected %d characters but got %d" % ( + payload_size, len(payload)) + else: + # Confirm the payload contains the correct characters. + for i in range(len(payload)): + if i <= len(payload_parts[0]): + continue + c = payload[i:i+1] + if c != b"*": + error = u"expected '*' at index %d but got '%s''" % ( + i, isomorphic_decode(c)) + break + + # Store the result in the stash so that it can be retrieved + # later with a 'stat' command. + request.server.stash.put(id, { + u"error": error, + u"type": isomorphic_decode(contentType) + }) + elif request.method == u"OPTIONS": + # If we expect a preflight, then add the cors headers we expect, + # otherwise log an error as we shouldn't send a preflight for all + # requests. + if b"preflightExpected" in request.GET: + response.headers.set(b"Access-Control-Allow-Headers", + b"content-type") + response.headers.set(b"Access-Control-Allow-Methods", b"POST") + else: + error = u"Preflight not expected." + request.server.stash.put(id, {u"error": error}) + elif command == b"stat": + test_data = request.server.stash.take(id) + results = [test_data] if test_data else [] + + response.headers.set(b"Content-Type", b"text/plain") + response.content = json.dumps(results) + else: + response.status = 400 # BadRequest |