Simple API with AWS Lambda function URL

You need to create a "simple" API? Try out the Lambda function URL

a year ago   •   3 min read

By Denys Burdeniuk
Image by Freepik
Table of contents

In case you need to create an API for "internal" usage or you you would like to invoke some Lambda function in the AWS by sending some request to API endpoint, you can create it with Lambda function URL.

Benefits:

  • less resources to maintain (no API Gateway needed)
  • architecture is simpler (just Lambda basically)
  • costs less (no API Gateway, you pay only for Lambda invocations)
  • easier to create (required minimum: Lambda, URL for it, role/policies)
  • limit for execution time is 15 min (API Gateway has limit of 29 sec)
  • possible to set up IAM auth (similar to API Gateway)

Down sides:

  • no API Gateway - means less customisation and control over some moments (no Usage plan, no AWS WAF security, no other fine-tuning options from API Gateway)
  • no straightforward possibility to set up a custom domain for Lambda URL (there may be a workaround, but it is out of scope of this article)
  • maybe the AWS region where you want to create Lambda function URL does not support it yet (on time of writing this article the Lambda function URL is not supported in Asia Pacific (Hyderabad) (ap-south-2), Asia Pacific (Melbourne) (ap-southeast-4), Europe (Spain) (eu-south-2), Europe (Zurich) (eu-central-2), Israel (Tel Aviv) (il-central-1), and Middle East (UAE) (me-central-1)

How URL will look like

Once the URL is generated for Lambda function it will not be changed after Lambda updates/redeployment. It will be regenerated only if URL-resource is removed from Lambda and then created again.

Generated URL looks like: https://{generated-part}.lambda-url.{region}.on.aws

Example: https://uwdlljsl2xfjwufk12x5gst.lambda-url.us-east-1.on.aws

Authentication options and code examples

Option 1 - NONE (no authentication)

It is possible to not have authentication for Lambda function URL at all and in this case URL will be publicly accessible. It may be that it is exactly what you want, but keep in mind that you do not have built in AWS WAF support and other security options that API Gateway would provide.

Example 1. Lambda function URL with auth NONE defined as infrastructure as code in python using aws-cdk:

api_lambda = Function(
    self,
    function_name=«SomeLambdaName»,
    code=Code.from_asset(
        path="",
        exclude=[
            "tests"
        ],
    ),
    handler=«src.api_lambda.handler»,
    runtime=Runtime.PYTHON_3_11,
)


api_lambda.add_function_url(
    auth_type=FunctionUrlAuthType.NONE
)

Option 2 - AWS_IAM authentication

In this case only authenticated AWS users and roles can invoke Lambda URL.

If you are going to call the Lambda URL from the same AWS account then you need to set AWS_IAM auth type for Lambda URL and add next identity-based policy to role/user that is going to call the lambda URL:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "InvokeLambdaURL",
            "Effect": "Allow",
            "Action": "lambda:InvokeFunctionUrl",
            "Resource": "arn:aws:lambda:{aws_region}:{aws_account_id}:function:{lambda_function_name}"
        }
    ]
}

If you are going to call the Lambda URL from different AWS account then you need to set AWS_IAM auth type for Lambda URL, add the same identity-based policy to role/user that is going to call the lambda URL (defined above) and also you need to add resource-based policy to lambda function that provides URL itself - principal has to be the account from where the requests will be made.

Example 2. Lambda function URL with auth AWS_IAM. Lambda is callable by resources from the same and also from other AWS account. Defined as infrastructure as code in python using aws-cdk:

api_lambda = Function(
    self,
    function_name="SomeLambdaName",
    code=Code.from_asset(
        path="",
        exclude=[
            "tests"
        ],
    ),
    handler="src.api_lambda.handler",
    runtime=Runtime.PYTHON_3_11,
)

api_lambda.add_permission(
    id="PolicyToAllowCrossAccountExecution",
    action="lambda:InvokeFunctionUrl",
    principal=AccountPrincipal(account_id=your_other_aws_account_id),
    function_url_auth_type=FunctionUrlAuthType.AWS_IAM,
)

api_lambda.add_function_url(
    auth_type=FunctionUrlAuthType.AWS_IAM
)

Example 3. Code of lambda function (to give you a basic overview and idea). Defined in python:

def handler(event, context):
    # check it out what values you can get from event param here: https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html#urls-payloads

    # Request validation (if it fails you may want to return statusCode: 400)
    # Other usecase actions, etc

    # Successful result return
    return {
        "statusCode": 200,
        "body": json.dumps({"key": "value"}),
    }

Conclusion and recommendation

Lambda function URL is a nice feature that allows you to create simple APIs. It does not have advanced features such as API Gateway provides, therefore we would recommend Lambda function URL for simple APIs for internal usage with IAM auth.

Additional information

https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html

Spread the word

Keep reading