Best Python code snippet using localstack_python
lambda_api.py
Source:lambda_api.py
...286 continue287 for key, value in dict(attr).items():288 attr[first_char_to_lower(key)] = attr.pop(key)289 return message_attrs290def process_lambda_url_invocation(lambda_url_config: dict, event: dict):291 inv_result = run_lambda(292 func_arn=lambda_url_config["FunctionArn"],293 event=event,294 asynchronous=False,295 )296 return inv_result.result297def get_event_sources(func_name=None, source_arn=None):298 result = []299 for region, details in LambdaRegion.regions().items():300 for m in details.event_source_mappings:301 if not func_name or (m["FunctionArn"] in [func_name, func_arn(func_name)]):302 if event_source_arn_matches(mapped=m.get("EventSourceArn"), searched=source_arn):303 result.append(m)304 return result305def get_function_version(arn, version):306 region = LambdaRegion.get()307 func = region.lambdas.get(arn)308 return format_func_details(func, version=version, always_add_version=True)309def publish_new_function_version(arn):310 region = LambdaRegion.get()311 lambda_function = region.lambdas.get(arn)312 versions = lambda_function.versions313 max_version_number = lambda_function.max_version()314 next_version_number = max_version_number + 1315 latest_hash = versions.get(VERSION_LATEST).get("CodeSha256")316 max_version = versions.get(str(max_version_number))317 max_version_hash = max_version.get("CodeSha256") if max_version else ""318 if latest_hash != max_version_hash:319 versions[str(next_version_number)] = {320 "CodeSize": versions.get(VERSION_LATEST).get("CodeSize"),321 "CodeSha256": versions.get(VERSION_LATEST).get("CodeSha256"),322 "Function": versions.get(VERSION_LATEST).get("Function"),323 "RevisionId": str(uuid.uuid4()),324 }325 max_version_number = next_version_number326 return get_function_version(arn, str(max_version_number))327def do_list_versions(arn):328 region = LambdaRegion.get()329 versions = [330 get_function_version(arn, version) for version in region.lambdas.get(arn).versions.keys()331 ]332 return sorted(versions, key=lambda k: str(k.get("Version")))333def do_update_alias(arn, alias, version, description=None):334 region = LambdaRegion.get()335 new_alias = {336 "AliasArn": arn + ":" + alias,337 "FunctionVersion": version,338 "Name": alias,339 "Description": description or "",340 "RevisionId": str(uuid.uuid4()),341 }342 region.lambdas.get(arn).aliases[alias] = new_alias343 return new_alias344def run_lambda(345 func_arn,346 event,347 context=None,348 version=None,349 suppress_output=False,350 asynchronous=False,351 callback=None,352 lock_discriminator: str = None,353) -> InvocationResult:354 if context is None:355 context = {}356 # Ensure that the service provider has been initialized. This is required to ensure all lifecycle hooks357 # (e.g., persistence) have been executed when the run_lambda(..) function gets called (e.g., from API GW).358 if not hasattr(run_lambda, "_provider_initialized"):359 aws_stack.connect_to_service("lambda").list_functions()360 run_lambda._provider_initialized = True361 region_name = extract_region_from_arn(func_arn)362 region = LambdaRegion.get(region_name)363 if suppress_output:364 stdout_ = sys.stdout365 stderr_ = sys.stderr366 stream = StringIO()367 sys.stdout = stream368 sys.stderr = stream369 try:370 func_arn = aws_stack.fix_arn(func_arn)371 lambda_function = region.lambdas.get(func_arn)372 if not lambda_function:373 LOG.debug("Unable to find details for Lambda %s in region %s", func_arn, region_name)374 result = not_found_error(msg="The resource specified in the request does not exist.")375 return InvocationResult(result)376 if lambda_function.state != "Active":377 result = error_response(378 f"The operation cannot be performed at this time. The function is currently in the following state: {lambda_function.state}",379 409,380 "ResourceConflictException",381 )382 raise ClientError(result)383 context = LambdaContext(lambda_function, version, context)384 result = LAMBDA_EXECUTOR.execute(385 func_arn,386 lambda_function,387 event,388 context=context,389 version=version,390 asynchronous=asynchronous,391 callback=callback,392 lock_discriminator=lock_discriminator,393 )394 return result395 except ClientError:396 raise397 except Exception as e:398 exc_type, exc_value, exc_traceback = sys.exc_info()399 response = {400 "errorType": str(exc_type.__name__),401 "errorMessage": str(e),402 "stackTrace": traceback.format_tb(exc_traceback),403 }404 LOG.info("Error executing Lambda function %s: %s %s", func_arn, e, traceback.format_exc())405 if isinstance(e, lambda_executors.InvocationException):406 exc_result = e.result407 response = run_safe(lambda: json.loads(exc_result)) or response408 log_output = e.log_output if isinstance(e, lambda_executors.InvocationException) else ""409 return InvocationResult(Response(json.dumps(response), status=500), log_output)410 finally:411 if suppress_output:412 sys.stdout = stdout_413 sys.stderr = stderr_414def load_source(name, file):415 return importlib.machinery.SourceFileLoader(name, file).load_module()416def exec_lambda_code(script, handler_function="handler", lambda_cwd=None, lambda_env=None):417 # TODO: The code in this function is generally not thread-safe and potentially insecure418 # (e.g., mutating environment variables, and globally loaded modules). Should be redesigned.419 def _do_exec_lambda_code():420 if lambda_cwd or lambda_env:421 if lambda_cwd:422 previous_cwd = os.getcwd()423 os.chdir(lambda_cwd)424 sys.path = [lambda_cwd] + sys.path425 if lambda_env:426 previous_env = dict(os.environ)427 os.environ.update(lambda_env)428 # generate lambda file name429 lambda_id = "l_%s" % short_uid()430 lambda_file = LAMBDA_SCRIPT_PATTERN.replace("*", lambda_id)431 save_file(lambda_file, script)432 # delete temporary .py and .pyc files on exit433 TMP_FILES.append(lambda_file)434 TMP_FILES.append("%sc" % lambda_file)435 try:436 pre_sys_modules_keys = set(sys.modules.keys())437 # set default env variables required for most Lambda handlers438 env_vars_before = lambda_executors.LambdaExecutorLocal.set_default_env_variables()439 try:440 handler_module = load_source(lambda_id, lambda_file)441 module_vars = handler_module.__dict__442 finally:443 lambda_executors.LambdaExecutorLocal.reset_default_env_variables(env_vars_before)444 # the above import can bring files for the function445 # (eg settings.py) into the global namespace. subsequent446 # calls can pick up file from another function, causing447 # general issues.448 post_sys_modules_keys = set(sys.modules.keys())449 for key in post_sys_modules_keys:450 if key not in pre_sys_modules_keys:451 sys.modules.pop(key)452 except Exception as e:453 LOG.error("Unable to exec: %s %s", script, traceback.format_exc())454 raise e455 finally:456 if lambda_cwd or lambda_env:457 if lambda_cwd:458 os.chdir(previous_cwd)459 sys.path.pop(0)460 if lambda_env:461 os.environ = previous_env462 return module_vars[handler_function]463 lock = EXEC_MUTEX if lambda_cwd or lambda_env else empty_context_manager()464 with lock:465 return _do_exec_lambda_code()466def get_handler_function_from_name(handler_name, runtime=None):467 runtime = runtime or LAMBDA_DEFAULT_RUNTIME468 if runtime.startswith(tuple(DOTNET_LAMBDA_RUNTIMES)):469 return handler_name.split(":")[-1]470 return handler_name.split(".")[-1]471def get_java_handler(zip_file_content, main_file, lambda_function=None):472 """Creates a Java handler from an uploaded ZIP or JAR.473 :type zip_file_content: bytes474 :param zip_file_content: ZIP file bytes.475 :type handler: str476 :param handler: The lambda handler path.477 :type main_file: str478 :param main_file: Filepath to the uploaded ZIP or JAR file.479 :returns: function or flask.Response480 """481 if is_zip_file(zip_file_content):482 def execute(event, context):483 result = lambda_executors.EXECUTOR_LOCAL.execute_java_lambda(484 event, context, main_file=main_file, lambda_function=lambda_function485 )486 return result487 return execute488 raise ClientError(489 error_response(490 "Unable to extract Java Lambda handler - file is not a valid zip/jar file (%s, %s bytes)"491 % (main_file, len(zip_file_content or "")),492 400,493 error_type="ValidationError",494 )495 )496def set_archive_code(code: Dict, lambda_name: str, zip_file_content: bytes = None) -> Optional[str]:497 region = LambdaRegion.get()498 # get metadata499 lambda_arn = func_arn(lambda_name)500 lambda_details = region.lambdas[lambda_arn]501 is_local_mount = code.get("S3Bucket") == config.BUCKET_MARKER_LOCAL502 if is_local_mount and config.LAMBDA_REMOTE_DOCKER:503 msg = 'Please note that Lambda mounts (bucket name "%s") cannot be used with LAMBDA_REMOTE_DOCKER=1'504 raise Exception(msg % config.BUCKET_MARKER_LOCAL)505 # Stop/remove any containers that this arn uses.506 LAMBDA_EXECUTOR.cleanup(lambda_arn)507 if is_local_mount:508 # Mount or use a local folder lambda executors can reference509 # WARNING: this means we're pointing lambda_cwd to a local path in the user's510 # file system! We must ensure that there is no data loss (i.e., we must *not* add511 # this folder to TMP_FILES or similar).512 lambda_details.cwd = code.get("S3Key")513 return code["S3Key"]514 # get file content515 zip_file_content = zip_file_content or get_zip_bytes(code)516 if not zip_file_content:517 return518 # Save the zip file to a temporary file that the lambda executors can reference519 code_sha_256 = base64.standard_b64encode(hashlib.sha256(zip_file_content).digest())520 latest_version = lambda_details.get_version(VERSION_LATEST)521 latest_version["CodeSize"] = len(zip_file_content)522 latest_version["CodeSha256"] = code_sha_256.decode("utf-8")523 zip_dir_name = f"function.zipfile.{short_uid()}"524 zip_dir = f"{config.dirs.tmp}/{zip_dir_name}"525 mkdir(zip_dir)526 tmp_file = f"{zip_dir}/{LAMBDA_ZIP_FILE_NAME}"527 save_file(tmp_file, zip_file_content)528 TMP_FILES.append(zip_dir)529 lambda_details.zip_dir = zip_dir530 lambda_details.cwd = f"{get_lambda_extraction_dir()}/{zip_dir_name}"531 mkdir(lambda_details.cwd)532 return zip_dir533def set_function_code(lambda_function: LambdaFunction):534 def _set_and_configure(*args, **kwargs):535 try:536 before = time.perf_counter()537 do_set_function_code(lambda_function)538 # initialize function code via plugins539 for plugin in lambda_executors.LambdaExecutorPlugin.get_plugins():540 plugin.init_function_code(lambda_function)541 lambda_function.state = "Active"542 LOG.debug(543 "Function code initialization for function '%s' complete. State => Active (in %.3fs)",544 lambda_function.name(),545 time.perf_counter() - before,546 )547 except Exception:548 lambda_function.state = "Failed"549 raise550 # unzipping can take some time - limit the execution time to avoid client/network timeout issues551 run_for_max_seconds(config.LAMBDA_CODE_EXTRACT_TIME, _set_and_configure)552 return {"FunctionName": lambda_function.name()}553def store_and_get_lambda_code_archive(554 lambda_function: LambdaFunction, zip_file_content: bytes = None555) -> Optional[Tuple[str, str, bytes]]:556 """Store the Lambda code referenced in the LambdaFunction details to disk as a zip file,557 and return the Lambda CWD, file name, and zip bytes content. May optionally return None558 in case this is a Lambda with the special bucket marker __local__, used for code mounting."""559 code_passed = lambda_function.code560 is_local_mount = code_passed.get("S3Bucket") == config.BUCKET_MARKER_LOCAL561 lambda_zip_dir = lambda_function.zip_dir562 if code_passed:563 lambda_zip_dir = lambda_zip_dir or set_archive_code(code_passed, lambda_function.name())564 if not zip_file_content and not is_local_mount:565 # Save the zip file to a temporary file that the lambda executors can reference566 zip_file_content = get_zip_bytes(code_passed)567 else:568 lambda_details = LambdaRegion.get().lambdas[lambda_function.arn()]569 lambda_zip_dir = lambda_zip_dir or lambda_details.zip_dir570 if not lambda_zip_dir:571 return572 # construct archive name573 archive_file = os.path.join(lambda_zip_dir, LAMBDA_ZIP_FILE_NAME)574 if not zip_file_content:575 zip_file_content = load_file(archive_file, mode="rb")576 else:577 # override lambda archive with fresh code if we got an update578 save_file(archive_file, zip_file_content)579 # remove content from code attribute, if present580 lambda_function.code.pop("ZipFile", None)581 return lambda_zip_dir, archive_file, zip_file_content582def do_set_function_code(lambda_function: LambdaFunction):583 """Main function that creates the local zip archive for the given Lambda function, and584 optionally creates the handler function references (for LAMBDA_EXECUTOR=local)"""585 def generic_handler(*_):586 raise ClientError(587 (588 'Unable to find executor for Lambda function "%s". Note that '589 + "Node.js, Golang, and .Net Core Lambdas currently require LAMBDA_EXECUTOR=docker"590 )591 % lambda_name592 )593 lambda_name = lambda_function.name()594 arn = lambda_function.arn()595 runtime = get_lambda_runtime(lambda_function)596 lambda_environment = lambda_function.envvars597 handler_name = lambda_function.handler = lambda_function.handler or LAMBDA_DEFAULT_HANDLER598 code_passed = lambda_function.code599 is_local_mount = code_passed.get("S3Bucket") == config.BUCKET_MARKER_LOCAL600 # cleanup any left-over Lambda executor instances601 LAMBDA_EXECUTOR.cleanup(arn)602 # get local Lambda code archive path603 _result = store_and_get_lambda_code_archive(lambda_function)604 if not _result:605 return606 lambda_zip_dir, archive_file, zip_file_content = _result607 lambda_cwd = lambda_function.cwd608 # Set the appropriate Lambda handler.609 lambda_handler = generic_handler610 is_java = lambda_executors.is_java_lambda(runtime)611 if is_java:612 # The Lambda executors for Docker subclass LambdaExecutorContainers, which613 # runs Lambda in Docker by passing all *.jar files in the function working614 # directory as part of the classpath. Obtain a Java handler function below.615 try:616 lambda_handler = get_java_handler(617 zip_file_content, archive_file, lambda_function=lambda_function618 )619 except Exception as e:620 # this can happen, e.g., for Lambda code mounted via __local__ -> ignore621 LOG.debug("Unable to determine Lambda Java handler: %s", e)622 if not is_local_mount:623 # Lambda code must be uploaded in Zip format624 if not is_zip_file(zip_file_content):625 raise ClientError(f"Uploaded Lambda code for runtime ({runtime}) is not in Zip format")626 # Unzip the Lambda archive contents627 if get_unzipped_size(archive_file) >= FUNCTION_MAX_UNZIPPED_SIZE:628 raise ClientError(629 error_response(630 f"Unzipped size must be smaller than {FUNCTION_MAX_UNZIPPED_SIZE} bytes",631 code=400,632 error_type="InvalidParameterValueException",633 )634 )635 unzip(archive_file, lambda_cwd)636 # Obtain handler details for any non-Java Lambda function637 if not is_java:638 handler_file = get_handler_file_from_name(handler_name, runtime=runtime)639 main_file = f"{lambda_cwd}/{handler_file}"640 if CHECK_HANDLER_ON_CREATION and not os.path.exists(main_file):641 # Raise an error if (1) this is not a local mount lambda, or (2) we're642 # running Lambdas locally (not in Docker), or (3) we're using remote Docker.643 # -> We do *not* want to raise an error if we're using local mount in non-remote Docker644 if not is_local_mount or not use_docker() or config.LAMBDA_REMOTE_DOCKER:645 file_list = run(f'cd "{lambda_cwd}"; du -d 3 .')646 config_debug = f'Config for local mount, docker, remote: "{is_local_mount}", "{use_docker()}", "{config.LAMBDA_REMOTE_DOCKER}"'647 LOG.debug("Lambda archive content:\n%s", file_list)648 raise ClientError(649 error_response(650 f"Unable to find handler script ({main_file}) in Lambda archive. {config_debug}",651 400,652 error_type="ValidationError",653 )654 )655 # TODO: init code below should be moved into LambdaExecutorLocal!656 if runtime.startswith("python") and not use_docker():657 try:658 # make sure the file is actually readable, then read contents659 ensure_readable(main_file)660 zip_file_content = load_file(main_file, mode="rb")661 # extract handler662 handler_function = get_handler_function_from_name(handler_name, runtime=runtime)663 lambda_handler = exec_lambda_code(664 zip_file_content,665 handler_function=handler_function,666 lambda_cwd=lambda_cwd,667 lambda_env=lambda_environment,668 )669 except Exception as e:670 raise ClientError("Unable to get handler function from lambda code: %s" % e)671 if runtime.startswith("node") and not use_docker():672 ensure_readable(main_file)673 def execute(event, context):674 result = lambda_executors.EXECUTOR_LOCAL.execute_javascript_lambda(675 event, context, main_file=main_file, lambda_function=lambda_function676 )677 return result678 lambda_handler = execute679 if runtime.startswith("go1") and not use_docker():680 install_go_lambda_runtime()681 ensure_readable(main_file)682 def execute_go(event, context):683 result = lambda_executors.EXECUTOR_LOCAL.execute_go_lambda(684 event, context, main_file=main_file, lambda_function=lambda_function685 )686 return result687 lambda_handler = execute_go688 if lambda_handler:689 lambda_executors.LambdaExecutorLocal.add_function_callable(lambda_function, lambda_handler)690 return lambda_handler691def do_list_functions():692 funcs = []693 region = LambdaRegion.get()694 this_region = aws_stack.get_region()695 for f_arn, func in region.lambdas.items():696 if type(func) != LambdaFunction:697 continue698 # filter out functions of current region699 func_region = extract_region_from_arn(f_arn)700 if func_region != this_region:701 continue702 func_name = f_arn.split(":function:")[-1]703 arn = func_arn(func_name)704 lambda_function = region.lambdas.get(arn)705 if not lambda_function:706 # this can happen if we're accessing Lambdas from a different region (ARN mismatch)707 continue708 details = format_func_details(lambda_function)709 details["Tags"] = func.tags710 funcs.append(details)711 return funcs712def format_func_details(713 lambda_function: LambdaFunction, version: str = None, always_add_version=False714) -> Dict[str, Any]:715 version = version or VERSION_LATEST716 func_version = lambda_function.get_version(version)717 result = {718 "CodeSha256": func_version.get("CodeSha256"),719 "Role": lambda_function.role,720 "KMSKeyArn": lambda_function.kms_key_arn,721 "Version": version,722 "VpcConfig": lambda_function.vpc_config,723 "FunctionArn": lambda_function.arn(),724 "FunctionName": lambda_function.name(),725 "CodeSize": func_version.get("CodeSize"),726 "Handler": lambda_function.handler,727 "Runtime": lambda_function.runtime,728 "Timeout": lambda_function.timeout,729 "Description": lambda_function.description,730 "MemorySize": lambda_function.memory_size,731 "LastModified": format_timestamp(lambda_function.last_modified),732 "TracingConfig": lambda_function.tracing_config or {"Mode": "PassThrough"},733 "RevisionId": func_version.get("RevisionId"),734 "State": lambda_function.state,735 "LastUpdateStatus": "Successful",736 "PackageType": lambda_function.package_type,737 "ImageConfig": getattr(lambda_function, "image_config", None),738 "Architectures": lambda_function.architectures,739 }740 if lambda_function.dead_letter_config:741 result["DeadLetterConfig"] = lambda_function.dead_letter_config742 if lambda_function.envvars:743 result["Environment"] = {"Variables": lambda_function.envvars}744 arn_parts = result["FunctionArn"].split(":")745 if (always_add_version or version != VERSION_LATEST) and len(arn_parts) <= 7:746 result["FunctionArn"] += ":%s" % version747 return result748def forward_to_fallback_url(func_arn, data):749 """If LAMBDA_FALLBACK_URL is configured, forward the invocation of this non-existing750 Lambda to the configured URL."""751 if not config.LAMBDA_FALLBACK_URL:752 return753 lambda_name = aws_stack.lambda_function_name(func_arn)754 if config.LAMBDA_FALLBACK_URL.startswith("dynamodb://"):755 table_name = urlparse(config.LAMBDA_FALLBACK_URL.replace("dynamodb://", "http://")).netloc756 dynamodb = aws_stack.connect_to_service("dynamodb")757 item = {758 "id": {"S": short_uid()},759 "timestamp": {"N": str(now_utc())},760 "payload": {"S": data},761 "function_name": {"S": lambda_name},762 }763 aws_stack.create_dynamodb_table(table_name, partition_key="id")764 dynamodb.put_item(TableName=table_name, Item=item)765 return ""766 if re.match(r"^https?://.+", config.LAMBDA_FALLBACK_URL):767 headers = {768 "lambda-function-name": lambda_name,769 "Content-Type": APPLICATION_JSON,770 }771 response = safe_requests.post(config.LAMBDA_FALLBACK_URL, data, headers=headers)772 content = response.content773 try:774 # parse the response into a dictionary to get details775 # like function error etc.776 content = json.loads(content)777 except Exception:778 pass779 return content780 raise ClientError("Unexpected value for LAMBDA_FALLBACK_URL: %s" % config.LAMBDA_FALLBACK_URL)781def get_lambda_policy(function, qualifier=None):782 iam_client = aws_stack.connect_to_service("iam")783 policies = iam_client.list_policies(Scope="Local", MaxItems=500)["Policies"]784 docs = []785 for p in policies:786 # !TODO: Cache policy documents instead of running N+1 API calls here!787 versions = iam_client.list_policy_versions(PolicyArn=p["Arn"])["Versions"]788 default_version = [v for v in versions if v.get("IsDefaultVersion")]789 versions = default_version or versions790 doc = versions[0]["Document"]791 doc = doc if isinstance(doc, dict) else json.loads(doc)792 if not isinstance(doc["Statement"], list):793 doc["Statement"] = [doc["Statement"]]794 for stmt in doc["Statement"]:795 stmt["Principal"] = stmt.get("Principal") or {"AWS": get_aws_account_id()}796 doc["PolicyArn"] = p["Arn"]797 doc["PolicyName"] = p["PolicyName"]798 doc["Id"] = "default"799 docs.append(doc)800 # find policy by name801 policy_name = get_lambda_policy_name(802 aws_stack.lambda_function_name(function), qualifier=qualifier803 )804 policy = [d for d in docs if d["PolicyName"] == policy_name]805 if policy:806 return policy[0]807 # find policy by target Resource in statement (TODO: check if this heuristic holds in the general case)808 res_qualifier = func_qualifier(function, qualifier)809 policy = [d for d in docs if d["Statement"][0]["Resource"] == res_qualifier]810 return (policy or [None])[0]811def get_lambda_policy_name(resource_name: str, qualifier: str = None) -> str:812 qualifier = qualifier or "latest"813 if ":function:" in resource_name:814 resource_name = function_name_from_arn(resource_name)815 return LAMBDA_POLICY_NAME_PATTERN.format(name=resource_name, qualifier=qualifier)816def lookup_function(function, region, request_url):817 result = {818 "Configuration": function,819 "Code": {"Location": "%s/code" % request_url},820 "Tags": function["Tags"],821 }822 lambda_details = region.lambdas.get(function["FunctionArn"])823 # patch for image lambdas (still missing RepositoryType and ResolvedImageUri)824 # please note that usage is still only available with a PRO license825 if lambda_details.package_type == "Image":826 result["Code"] = lambda_details.code827 result["Configuration"]["CodeSize"] = 0828 result["Configuration"].pop("Handler", None)829 result["Configuration"].pop("Layers", None)830 if lambda_details.concurrency is not None:831 result["Concurrency"] = lambda_details.concurrency832 return jsonify(result)833def not_found_error(ref=None, msg=None):834 if not msg:835 msg = "The resource you requested does not exist."836 if ref:837 msg = "%s not found: %s" % (838 "Function" if ":function:" in ref else "Resource",839 ref,840 )841 return error_response(msg, 404, error_type="ResourceNotFoundException")842def delete_lambda_function(function_name: str) -> Dict[None, None]:843 arn = func_arn(function_name)844 region = LambdaRegion.get()845 # Stop/remove any containers that this arn uses.846 LAMBDA_EXECUTOR.cleanup(arn)847 try:848 region.lambdas.pop(arn)849 except KeyError:850 raise ResourceNotFoundException(851 f"Unable to delete non-existing Lambda function {func_arn(function_name)}"852 )853 i = 0854 while i < len(region.event_source_mappings):855 mapping = region.event_source_mappings[i]856 if mapping["FunctionArn"] == arn:857 del region.event_source_mappings[i]858 i -= 1859 i += 1860 return {}861def get_lambda_url_config(api_id, region=None):862 lambda_backend = LambdaRegion.get(region)863 url_configs = lambda_backend.url_configs.values()864 lambda_url_configs = [config for config in url_configs if config.get("CustomId") == api_id]865 return lambda_url_configs[0]866def event_for_lambda_url(api_id, path, data, headers, method) -> dict:867 raw_path = path.split("?")[0]868 raw_query_string = path.split("?")[1] if len(path.split("?")) > 1 else ""869 query_string_parameters = (870 {} if not raw_query_string else dict(urllib.parse.parse_qsl(raw_query_string))871 )872 now = datetime.utcnow()873 readable = timestamp(time=now, format=TIMESTAMP_READABLE_FORMAT)874 if not any(char in readable for char in ["+", "-"]):875 readable += "+0000"876 source_ip = headers.get("Remote-Addr", "")877 request_context = {878 "accountId": "anonymous",879 "apiId": api_id,880 "domainName": headers.get("Host", ""),881 "domainPrefix": api_id,882 "http": {883 "method": method,884 "path": raw_path,885 "protocol": "HTTP/1.1",886 "sourceIp": source_ip,887 "userAgent": headers.get("User-Agent", ""),888 },889 "requestId": long_uid(),890 "routeKey": "$default",891 "stage": "$default",892 "time": readable,893 "timeEpoch": mktime(ts=now, millis=True),894 }895 content_type = headers.get("Content-Type", "").lower()896 content_type_is_text = any(text_type in content_type for text_type in ["text", "json", "xml"])897 is_base64_encoded = not (data.isascii() and content_type_is_text) if data else False898 body = base64.b64encode(data).decode() if is_base64_encoded else data899 ignored_headers = ["connection", "x-localstack-tgt-api", "x-localstack-request-url"]900 event_headers = {k.lower(): v for k, v in headers.items() if k.lower() not in ignored_headers}901 event_headers.update(902 {903 "x-amzn-tls-cipher-suite": "ECDHE-RSA-AES128-GCM-SHA256",904 "x-amzn-tls-version": "TLSv1.2",905 "x-forwarded-proto": "http",906 "x-forwarded-for": source_ip,907 "x-forwarded-port": str(config.EDGE_PORT),908 }909 )910 event = {911 "version": "2.0",912 "routeKey": "$default",913 "rawPath": raw_path,914 "rawQueryString": raw_query_string,915 "headers": event_headers,916 "queryStringParameters": query_string_parameters,917 "requestContext": request_context,918 "body": body,919 "isBase64Encoded": is_base64_encoded,920 }921 if not data:922 event.pop("body")923 return event924def handle_lambda_url_invocation(925 request: Request, api_id: str, region: str, **url_params: Dict[str, str]926) -> HttpResponse:927 response = HttpResponse(headers={"Content-type": "application/json"})928 try:929 lambda_url_config = get_lambda_url_config(api_id, region)930 except IndexError as e:931 LOG.warning(f"Lambda URL ({api_id}) not found: {e}")932 response.set_json({"Message": None})933 response.status = "404"934 return response935 event = event_for_lambda_url(936 api_id, request.full_path, request.data, request.headers, request.method937 )938 try:939 result = process_lambda_url_invocation(lambda_url_config, event)940 except Exception as e:941 LOG.warning(f"Lambda URL ({api_id}) failed during execution: {e}")942 response.set_json({"Message": "lambda function failed during execution"})943 response.status = "403"944 return response945 response = lambda_result_to_response(result)946 return response947def json_or_eval(body: str):948 try:949 return json.loads(body)950 except JSONDecodeError:951 try:952 return ast.literal_eval(body)953 except Exception as e:...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!