| """An HTTP request handler for WPT that handles /set_beacon.py requests.""" |
| |
| _BEACON_ID_KEY = b"uuid" |
| _BEACON_DATA_PATH = "beacon_data" |
| _BEACON_FORM_PAYLOAD_KEY = b"payload" |
| _BEACON_BODY_PAYLOAD_KEY = "payload=" |
| _BEACON_EXPECT_ORIGIN_KEY = b"expectOrigin" |
| _BEACON_EXPECT_PREFLIGHT_KEY = b"expectPreflight" |
| _BEACON_EXPECT_CREDS_KEY = b"expectCredentials" |
| |
| |
| def main(request, response): |
| """Stores the given beacon's data keyed by uuid in the server. |
| |
| For GET request, this handler assumes no data. |
| For POST request, this handler extracts data from request body: |
| - Content-Type=multipart/form-data: data keyed by 'payload'. |
| - the entire request body. |
| |
| Multiple data can be added for the same uuid. |
| |
| The data is stored as UTF-8 format. |
| """ |
| if _BEACON_ID_KEY not in request.GET: |
| response.status = 400 |
| return "Must provide a UUID to store beacon data" |
| uuid = request.GET.first(_BEACON_ID_KEY) |
| |
| expected_origin = request.GET.get(_BEACON_EXPECT_ORIGIN_KEY) |
| if b"origin" in request.headers: |
| origin = request.headers.get(b"origin") |
| if expected_origin: |
| assert origin == expected_origin, f"expected {expected_origin}, got {origin}" |
| response.headers.set(b"Access-Control-Allow-Origin", origin) |
| else: |
| assert expected_origin is None, f"expected None, got {expected_origin}" |
| |
| # Handles preflight request first. |
| if request.method == u"OPTIONS": |
| assert request.GET.get( |
| _BEACON_EXPECT_PREFLIGHT_KEY) == b"true", "Preflight not expected." |
| |
| # preflight must not have cookies. |
| assert b"Cookie" not in request.headers |
| |
| requested_headers = request.headers.get( |
| b"Access-Control-Request-Headers") |
| assert b"content-type" in requested_headers, f"expected content-type, got {requested_headers}" |
| response.headers.set(b"Access-Control-Allow-Headers", b"content-type") |
| |
| requested_method = request.headers.get(b"Access-Control-Request-Method") |
| assert requested_method == b"POST", f"expected POST, got {requested_method}" |
| response.headers.set(b"Access-Control-Allow-Methods", b"POST") |
| |
| return response |
| |
| expect_creds = request.GET.get(_BEACON_EXPECT_CREDS_KEY) == b"true" |
| if expect_creds: |
| assert b"Cookie" in request.headers |
| else: |
| assert b"Cookie" not in request.headers |
| |
| data = None |
| if request.method == u"POST": |
| if b"multipart/form-data" in request.headers.get(b"Content-Type", b""): |
| if _BEACON_FORM_PAYLOAD_KEY in request.POST: |
| data = request.POST.first(_BEACON_FORM_PAYLOAD_KEY).decode( |
| 'utf-8') |
| elif request.body: |
| data = request.body.decode('utf-8') |
| if data.startswith(_BEACON_BODY_PAYLOAD_KEY): |
| data = data.split(_BEACON_BODY_PAYLOAD_KEY)[1] |
| |
| with request.server.stash.lock: |
| saved_data = request.server.stash.take(key=uuid, path=_BEACON_DATA_PATH) |
| if not saved_data: |
| saved_data = [data] |
| else: |
| saved_data.append(data) |
| request.server.stash.put( |
| key=uuid, value=saved_data, path=_BEACON_DATA_PATH) |
| |
| response.status = 200 |