def load_data_from_request(request): data = None if request.method == "POST": if request.content_type in ["", "text/plain", "application/json"]: data = request.body else: data = request.POST.get("data") else: data = request.GET.get("data") if not data: return None # add the data in sentry's scope in case there's an exception with push_scope() as scope: scope.set_context("data", data) compression = (request.GET.get("compression") or request.POST.get("compression") or request.headers.get("content-encoding", "")) compression = compression.lower() if compression == "gzip" or compression == "gzip-js": try: data = gzip.decompress(data) except (EOFError, OSError) as error: raise RequestParsingError("Failed to decompress data. %s" % (str(error))) if compression == "lz64": if not isinstance(data, str): data = data.decode() data = data.replace(" ", "+") data = lzstring.LZString().decompressFromBase64(data) if not data: raise RequestParsingError("Failed to decompress data.") data = data.encode("utf-16", "surrogatepass").decode("utf-16") base64_decoded = None try: base64_decoded = base64_decode(data) except Exception: pass if base64_decoded: data = base64_decoded try: # parse_constant gets called in case of NaN, Infinity etc # default behaviour is to put those into the DB directly # but we just want it to return None data = json.loads(data, parse_constant=lambda x: None) except (json.JSONDecodeError, UnicodeDecodeError) as error_main: raise RequestParsingError("Invalid JSON: %s" % (str(error_main))) # TODO: data can also be an array, function assumes it's either None or a dictionary. return data
def load_data_from_request(request): data = None if request.method == "POST": if request.content_type in ["", "text/plain", "application/json"]: data = request.body else: data = request.POST.get("data") else: data = request.GET.get("data") if not data: return None # add the data in sentry's scope in case there's an exception with configure_scope() as scope: scope.set_context("data", data) scope.set_tag("origin", request.META.get("REMOTE_HOST", "unknown")) scope.set_tag("referer", request.META.get("HTTP_REFERER", "unknown")) # since version 1.20.0 posthog-js adds its version to the `ver` query parameter as a debug signal here scope.set_tag("library.version", request.GET.get("ver", "unknown")) compression = ( request.GET.get("compression") or request.POST.get("compression") or request.headers.get("content-encoding", "") ) compression = compression.lower() if compression == "gzip" or compression == "gzip-js": if data == b"undefined": raise RequestParsingError( "data being loaded from the request body for decompression is the literal string 'undefined'" ) try: data = gzip.decompress(data) except (EOFError, OSError) as error: raise RequestParsingError("Failed to decompress data. %s" % (str(error))) if compression == "lz64": if not isinstance(data, str): data = data.decode() data = data.replace(" ", "+") data = lzstring.LZString().decompressFromBase64(data) if not data: raise RequestParsingError("Failed to decompress data.") data = data.encode("utf-16", "surrogatepass").decode("utf-16") base64_decoded = None try: base64_decoded = base64_decode(data) except Exception: pass if base64_decoded: data = base64_decoded try: # parse_constant gets called in case of NaN, Infinity etc # default behaviour is to put those into the DB directly # but we just want it to return None data = json.loads(data, parse_constant=lambda x: None) except (json.JSONDecodeError, UnicodeDecodeError) as error_main: raise RequestParsingError("Invalid JSON: %s" % (str(error_main))) # TODO: data can also be an array, function assumes it's either None or a dictionary. return data