{"pageProps":{"post":{"mdxSource":"var Component=(()=>{var h=Object.create;var t=Object.defineProperty;var p=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var m=Object.getPrototypeOf,N=Object.prototype.hasOwnProperty;var k=(a,n)=>()=>(n||a((n={exports:{}}).exports,n),n.exports),b=(a,n)=>{for(var s in n)t(a,s,{get:n[s],enumerable:!0})},l=(a,n,s,i)=>{if(n&&typeof n==\"object\"||typeof n==\"function\")for(let c of u(n))!N.call(a,c)&&c!==s&&t(a,c,{get:()=>n[c],enumerable:!(i=p(n,c))||i.enumerable});return a};var f=(a,n,s)=>(s=a!=null?h(m(a)):{},l(n||!a||!a.__esModule?t(s,\"default\",{value:a,enumerable:!0}):s,a)),y=a=>l(t({},\"__esModule\",{value:!0}),a);var r=k((v,o)=>{o.exports=_jsx_runtime});var L={};b(L,{default:()=>A,frontmatter:()=>w});var e=f(r()),w={slug:\"guide-to-lambda-function-urls\",date:\"2022-08-23\",title:\"Guide to AWS Lambda Function URLs\",tags:[\"AWS\",\"Lambda\",\"serverless\"],summary:\"Learn how to create dedicated HTTP(S) endpoints for Lambda functions without an API Gateway\",authors:[\"tlakomy\"]};function d(a){let n=Object.assign({p:\"p\",em:\"em\",a:\"a\",h2:\"h2\",span:\"span\",pre:\"pre\",code:\"code\",ul:\"ul\",li:\"li\",strong:\"strong\",blockquote:\"blockquote\",h3:\"h3\",table:\"table\",thead:\"thead\",tr:\"tr\",th:\"th\",tbody:\"tbody\",td:\"td\"},a.components);return(0,e.jsxs)(e.Fragment,{children:[(0,e.jsxs)(n.p,{children:[\"For the longest time, the go-to way of calling an AWS Lambda function via HTTP(S) was to put an API Gateway in front of it. While this works well (and it's still a required pattern for many, many serverless use cases), sometimes developers wanted to \",(0,e.jsx)(n.em,{children:'\"just call an AWS Lambda function\"'}),\" by sending a network request.\"]}),`\n`,(0,e.jsxs)(n.p,{children:[\"Introducing \",(0,e.jsx)(n.a,{href:\"https://aws.amazon.com/blogs/aws/announcing-aws-lambda-function-urls-built-in-https-endpoints-for-single-function-microservices/\",children:\"AWS Lambda Function URLs\"}),\" - a new feature in AWS Lambda that allows you to call a Lambda function without an API Gateway.\"]}),`\n`,(0,e.jsxs)(n.h2,{id:\"what-is-a-lambda-function-url\",children:[(0,e.jsx)(n.a,{\"aria-hidden\":\"true\",tabIndex:\"-1\",href:\"#what-is-a-lambda-function-url\",children:(0,e.jsx)(n.span,{className:\"icon icon-link\"})}),\"What is a Lambda Function URL?\"]}),`\n`,(0,e.jsx)(n.p,{children:\"Simply put - it's an URL that you can send a network request to to call a Lambda function. An example URL may look like this:\"}),`\n`,(0,e.jsx)(n.pre,{className:\"language-bash\",children:(0,e.jsx)(n.code,{className:\"language-bash code-highlight\",children:(0,e.jsx)(n.span,{className:\"code-line\",children:`https://vg7sczk62ycloct63yi3wjpoj40sgkuz.lambda-url.eu-central-1.on.aws/\n`})})}),`\n`,(0,e.jsx)(n.p,{children:\"or, in general:\"}),`\n`,(0,e.jsx)(n.pre,{className:\"language-bash\",children:(0,e.jsx)(n.code,{className:\"language-bash code-highlight\",children:(0,e.jsxs)(n.span,{className:\"code-line\",children:[\"https://\",(0,e.jsx)(n.span,{className:\"token operator\",children:\"<\"}),\"url-id\",(0,e.jsx)(n.span,{className:\"token operator\",children:\">\"}),\".lambda-url.\",(0,e.jsx)(n.span,{className:\"token operator\",children:\"<\"}),\"region\",(0,e.jsx)(n.span,{className:\"token operator\",children:\">\"}),`.on.aws/\n`]})})}),`\n`,(0,e.jsxs)(n.p,{children:[\"Lambda function URL can point to either \",(0,e.jsx)(n.code,{children:\"$LATEST\"}),\" or to an \",(0,e.jsx)(n.a,{href:\"https://docs.aws.amazon.com/lambda/latest/dg/configuration-aliases.html\",children:\"user-defined alias\"}),\". Even though no additional resources are required (e.g. API Gateway or an ALB), function URL is a separate CloudFormation resource which needs to be provisioned separately.\"]}),`\n`,(0,e.jsxs)(n.h2,{id:\"how-do-i-create-an-aws-lambda-function-url\",children:[(0,e.jsx)(n.a,{\"aria-hidden\":\"true\",tabIndex:\"-1\",href:\"#how-do-i-create-an-aws-lambda-function-url\",children:(0,e.jsx)(n.span,{className:\"icon icon-link\"})}),\"How do I create an AWS Lambda function URL?\"]}),`\n`,(0,e.jsx)(n.p,{children:\"You can create an AWS Lambda function URL via:\"}),`\n`,(0,e.jsxs)(n.ul,{children:[`\n`,(0,e.jsxs)(n.li,{children:[\"AWS Management Console (Cloudash team does \",(0,e.jsx)(n.strong,{children:\"not\"}),\" recommend so-called ClickOps for production usage, use IaC instead)\"]}),`\n`,(0,e.jsx)(n.li,{children:\"AWS CLI\"}),`\n`,(0,e.jsx)(n.li,{children:\"AWS CloudFormation\"}),`\n`,(0,e.jsx)(n.li,{children:\"AWS Serverless Application Model (AWS SAM)\"}),`\n`,(0,e.jsx)(n.li,{children:\"AWS CDK\"}),`\n`]}),`\n`,(0,e.jsxs)(n.h2,{id:\"could-you-give-me-an-example\",children:[(0,e.jsx)(n.a,{\"aria-hidden\":\"true\",tabIndex:\"-1\",href:\"#could-you-give-me-an-example\",children:(0,e.jsx)(n.span,{className:\"icon icon-link\"})}),\"Could you give me an example?\"]}),`\n`,(0,e.jsx)(n.p,{children:\"Sure thing, this is how one might create an AWS Lambda function + and a function url to call it directly using AWS CDK:\"}),`\n`,(0,e.jsx)(n.pre,{className:\"language-ts\",children:(0,e.jsxs)(n.code,{className:\"language-ts code-highlight\",children:[(0,e.jsxs)(n.span,{className:\"code-line\",children:[(0,e.jsx)(n.span,{className:\"token keyword\",children:\"import\"}),\" \",(0,e.jsx)(n.span,{className:\"token operator\",children:\"*\"}),\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"as\"}),\" cdk \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"from\"}),\" \",(0,e.jsx)(n.span,{className:\"token string\",children:'\"aws-cdk-lib\"'}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\";\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[(0,e.jsx)(n.span,{className:\"token keyword\",children:\"import\"}),\" \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"{\"}),\" Construct \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"}\"}),\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"from\"}),\" \",(0,e.jsx)(n.span,{className:\"token string\",children:'\"constructs\"'}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\";\"}),`\n`]}),(0,e.jsx)(n.span,{className:\"code-line\",children:`\n`}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[(0,e.jsx)(n.span,{className:\"token keyword\",children:\"export\"}),\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"class\"}),\" \",(0,e.jsx)(n.span,{className:\"token class-name\",children:\"LambdaUrlStack\"}),\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"extends\"}),\" \",(0,e.jsx)(n.span,{className:\"token class-name\",children:\"cdk\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"Stack \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"{\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" \",(0,e.jsx)(n.span,{className:\"token function\",children:\"constructor\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"(\"}),\"scope\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" Construct\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),\" id\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" \",(0,e.jsx)(n.span,{className:\"token builtin\",children:\"string\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),\" props\",(0,e.jsx)(n.span,{className:\"token operator\",children:\"?\"}),(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" cdk\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"StackProps\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\")\"}),\" \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"{\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"super\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"(\"}),\"scope\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),\" id\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),\" props\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\")\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\";\"}),`\n`]}),(0,e.jsx)(n.span,{className:\"code-line\",children:`\n`}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"const\"}),\" myLambda \",(0,e.jsx)(n.span,{className:\"token operator\",children:\"=\"}),\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"new\"}),\" \",(0,e.jsx)(n.span,{className:\"token class-name\",children:\"cdk\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"aws_lambda\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),(0,e.jsx)(n.span,{className:\"token function\",children:\"Function\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"(\"}),(0,e.jsx)(n.span,{className:\"token keyword\",children:\"this\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),\" \",(0,e.jsx)(n.span,{className:\"token string\",children:'\"myLambda\"'}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),\" \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"{\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" code\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" cdk\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"aws_lambda\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"Code\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),(0,e.jsx)(n.span,{className:\"token function\",children:\"fromAsset\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"(\"}),(0,e.jsx)(n.span,{className:\"token string\",children:'\"lambda\"'}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\")\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" handler\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" \",(0,e.jsx)(n.span,{className:\"token string\",children:'\"index.handler\"'}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" runtime\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" cdk\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"aws_lambda\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"Runtime\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),(0,e.jsx)(n.span,{className:\"token constant\",children:\"NODEJS_16_X\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"}\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\")\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\";\"}),`\n`]}),(0,e.jsx)(n.span,{className:\"code-line\",children:`\n`}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"const\"}),\" lambdaUrl \",(0,e.jsx)(n.span,{className:\"token operator\",children:\"=\"}),\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"new\"}),\" \",(0,e.jsx)(n.span,{className:\"token class-name\",children:\"cdk\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"aws_lambda\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),(0,e.jsx)(n.span,{className:\"token function\",children:\"CfnUrl\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"(\"}),(0,e.jsx)(n.span,{className:\"token keyword\",children:\"this\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),\" \",(0,e.jsx)(n.span,{className:\"token string\",children:'\"lambdaUrl\"'}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),\" \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"{\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" targetFunctionArn\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" myLambda\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"functionArn\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" authType\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" cdk\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"aws_lambda\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"FunctionUrlAuthType\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),(0,e.jsx)(n.span,{className:\"token constant\",children:\"NONE\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"}\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\")\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\";\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"}\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"}\"}),`\n`]})]})}),`\n`,(0,e.jsxs)(n.p,{children:[\"And yes, \",(0,e.jsx)(n.code,{children:\"authType: cdk.aws_lambda.FunctionUrlAuthType.NONE\"}),\" is not exactly secure. Keep reading to learn more:\"]}),`\n`,(0,e.jsxs)(n.h2,{id:\"security-and-auth-model-for-lambda-function-urls\",children:[(0,e.jsx)(n.a,{\"aria-hidden\":\"true\",tabIndex:\"-1\",href:\"#security-and-auth-model-for-lambda-function-urls\",children:(0,e.jsx)(n.span,{className:\"icon icon-link\"})}),\"Security and auth model for Lambda function URLs\"]}),`\n`,(0,e.jsxs)(n.p,{children:[\"Controlling access to Lambda function URLs is performed using the \",(0,e.jsx)(n.code,{children:\"AuthType\"}),\" parameter combined with \",(0,e.jsx)(n.a,{href:\"https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html\",children:\"resource-based policies\"}),\" attached to a particular function.\"]}),`\n`,(0,e.jsxs)(n.p,{children:[\"To quote AWS docs, there are two possible values of \",(0,e.jsx)(n.code,{children:\"AuthType\"}),\" parameter:\"]}),`\n`,(0,e.jsxs)(n.blockquote,{children:[`\n`,(0,e.jsxs)(n.ul,{children:[`\n`,(0,e.jsxs)(n.li,{children:[(0,e.jsx)(n.code,{children:\"AWS_IAM\"}),\" \\u2013 Lambda uses AWS Identity and Access Management (IAM) to authenticate and authorize requests based on the IAM principal's identity policy and the function's resource-based policy. Choose this option if you want only authenticated IAM users and roles to invoke your function via the function URL.\"]}),`\n`]}),`\n`]}),`\n`,(0,e.jsxs)(n.blockquote,{children:[`\n`,(0,e.jsxs)(n.ul,{children:[`\n`,(0,e.jsxs)(n.li,{children:[(0,e.jsx)(n.code,{children:\"NONE\"}),\" \\u2013 Lambda doesn't perform any authentication before invoking your function. However, your function's resource-based policy is always in effect and must grant public access before your function URL can receive requests. Choose this option to allow public, unauthenticated access to your function URL.\"]}),`\n`]}),`\n`]}),`\n`,(0,e.jsxs)(n.h3,{id:\"aws_iam-auth-type\",children:[(0,e.jsx)(n.a,{\"aria-hidden\":\"true\",tabIndex:\"-1\",href:\"#aws_iam-auth-type\",children:(0,e.jsx)(n.span,{className:\"icon icon-link\"})}),(0,e.jsx)(n.code,{children:\"AWS_IAM\"}),\" auth type\"]}),`\n`,(0,e.jsxs)(n.p,{children:[\"When a Lambda function URL has an \",(0,e.jsx)(n.code,{children:\"AWS_IAM\"}),\" \",(0,e.jsx)(n.code,{children:\"AuthType\"}),\" then whoever needs to invoke this particular Lambda function URL must have the \",(0,e.jsx)(n.code,{children:\"lambda:InvokeFunctionUrl\"}),\" permission for a particular Lambda function.\"]}),`\n`,(0,e.jsxs)(n.p,{children:[(0,e.jsx)(n.strong,{children:\"Note:\"}),\" \",(0,e.jsx)(n.code,{children:\"lambda:InvokeFunctionUrl\"}),\" is \",(0,e.jsx)(n.strong,{children:\"different\"}),\" than \",(0,e.jsx)(n.code,{children:\"lambda:InvokeFunction\"}),\", so you may need to adjust your IAM permissions accordingly when opting in to use this feature.\"]}),`\n`,(0,e.jsxs)(n.h3,{id:\"none-auth-type\",children:[(0,e.jsx)(n.a,{\"aria-hidden\":\"true\",tabIndex:\"-1\",href:\"#none-auth-type\",children:(0,e.jsx)(n.span,{className:\"icon icon-link\"})}),(0,e.jsx)(n.code,{children:\"NONE\"}),\" auth type\"]}),`\n`,(0,e.jsxs)(n.p,{children:[\"When a Lambda function URL \",(0,e.jsx)(n.code,{children:\"AuthType\"}),\" is set to \",(0,e.jsx)(n.code,{children:\"NONE\"}),\" then \",(0,e.jsx)(n.strong,{children:\"any\"}),\" unauthenticated user with your function URL can invoke your function - proceed with caution. This might be useful whenever you might want to allow public access to your function URL e.g. via a web browser.\"]}),`\n`,(0,e.jsxs)(n.p,{children:[\"Even though the auth type is set to \",(0,e.jsx)(n.code,{children:\"NONE\"}),\" and Lambda does not use IAM to authenticate requests to a function URL, whoever tries to the function needs to have the \",(0,e.jsx)(n.code,{children:\"lambda:InvokeFunctionUrl\"}),\" permissions.\"]}),`\n`,(0,e.jsx)(n.p,{children:\"An example function URL invoke policy for all unauthenticated principals:\"}),`\n`,(0,e.jsx)(n.pre,{children:(0,e.jsxs)(n.code,{className:\"code-highlight\",children:[(0,e.jsx)(n.span,{className:\"code-line\",children:`{\n`}),(0,e.jsx)(n.span,{className:\"code-line\",children:` \"Version\": \"2012-10-17\",\n`}),(0,e.jsx)(n.span,{className:\"code-line\",children:` \"Statement\": [\n`}),(0,e.jsx)(n.span,{className:\"code-line\",children:` {\n`}),(0,e.jsx)(n.span,{className:\"code-line\",children:` \"Effect\": \"Allow\",\n`}),(0,e.jsx)(n.span,{className:\"code-line\",children:` \"Principal\": \"*\",\n`}),(0,e.jsx)(n.span,{className:\"code-line\",children:` \"Action\": \"lambda:InvokeFunctionUrl\",\n`}),(0,e.jsx)(n.span,{className:\"code-line\",children:` \"Resource\": \"arn:aws:lambda:us-east-1:123456789012:function:my-function\",\n`}),(0,e.jsx)(n.span,{className:\"code-line\",children:` \"Condition\": {\n`}),(0,e.jsx)(n.span,{className:\"code-line\",children:` \"StringEquals\": {\n`}),(0,e.jsx)(n.span,{className:\"code-line\",children:` \"lambda:FunctionUrlAuthType\": \"NONE\"\n`}),(0,e.jsx)(n.span,{className:\"code-line\",children:` }\n`}),(0,e.jsx)(n.span,{className:\"code-line\",children:` }\n`}),(0,e.jsx)(n.span,{className:\"code-line\",children:` }\n`}),(0,e.jsx)(n.span,{className:\"code-line\",children:` ]\n`}),(0,e.jsx)(n.span,{className:\"code-line\",children:`}\n`})]})}),`\n`,(0,e.jsx)(n.p,{children:(0,e.jsx)(n.a,{href:\"https://docs.aws.amazon.com/lambda/latest/dg/urls-auth.html\",children:\"Source\"})}),`\n`,(0,e.jsxs)(n.p,{children:[\"When creating a function URL with auth type set to \",(0,e.jsx)(n.code,{children:\"NONE\"}),\" via the AWS Console or AWS SAM, the resource-based policy statement listed above will be automatically created for you. When e.g. using AWS SDK you'd need to create it yourself, example of how one might want to do this below:\"]}),`\n`,(0,e.jsx)(n.pre,{className:\"language-ts\",children:(0,e.jsxs)(n.code,{className:\"language-ts code-highlight\",children:[(0,e.jsxs)(n.span,{className:\"code-line\",children:[(0,e.jsx)(n.span,{className:\"token keyword\",children:\"import\"}),\" \",(0,e.jsx)(n.span,{className:\"token operator\",children:\"*\"}),\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"as\"}),\" cdk \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"from\"}),\" \",(0,e.jsx)(n.span,{className:\"token string\",children:'\"aws-cdk-lib\"'}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\";\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[(0,e.jsx)(n.span,{className:\"token keyword\",children:\"import\"}),\" \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"{\"}),\" Construct \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"}\"}),\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"from\"}),\" \",(0,e.jsx)(n.span,{className:\"token string\",children:'\"constructs\"'}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\";\"}),`\n`]}),(0,e.jsx)(n.span,{className:\"code-line\",children:`\n`}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[(0,e.jsx)(n.span,{className:\"token keyword\",children:\"export\"}),\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"class\"}),\" \",(0,e.jsx)(n.span,{className:\"token class-name\",children:\"LambdaUrlStack\"}),\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"extends\"}),\" \",(0,e.jsx)(n.span,{className:\"token class-name\",children:\"cdk\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"Stack \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"{\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" \",(0,e.jsx)(n.span,{className:\"token function\",children:\"constructor\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"(\"}),\"scope\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" Construct\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),\" id\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" \",(0,e.jsx)(n.span,{className:\"token builtin\",children:\"string\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),\" props\",(0,e.jsx)(n.span,{className:\"token operator\",children:\"?\"}),(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" cdk\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"StackProps\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\")\"}),\" \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"{\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"super\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"(\"}),\"scope\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),\" id\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),\" props\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\")\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\";\"}),`\n`]}),(0,e.jsx)(n.span,{className:\"code-line\",children:`\n`}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"const\"}),\" myLambda \",(0,e.jsx)(n.span,{className:\"token operator\",children:\"=\"}),\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"new\"}),\" \",(0,e.jsx)(n.span,{className:\"token class-name\",children:\"cdk\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"aws_lambda\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),(0,e.jsx)(n.span,{className:\"token function\",children:\"Function\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"(\"}),(0,e.jsx)(n.span,{className:\"token keyword\",children:\"this\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),\" \",(0,e.jsx)(n.span,{className:\"token string\",children:'\"myLambda\"'}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),\" \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"{\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" code\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" cdk\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"aws_lambda\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"Code\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),(0,e.jsx)(n.span,{className:\"token function\",children:\"fromAsset\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"(\"}),(0,e.jsx)(n.span,{className:\"token string\",children:'\"lambda\"'}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\")\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" handler\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" \",(0,e.jsx)(n.span,{className:\"token string\",children:'\"index.handler\"'}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" runtime\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" cdk\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"aws_lambda\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"Runtime\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),(0,e.jsx)(n.span,{className:\"token constant\",children:\"NODEJS_16_X\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"}\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\")\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\";\"}),`\n`]}),(0,e.jsx)(n.span,{className:\"code-line\",children:`\n`}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"const\"}),\" lambdaUrl \",(0,e.jsx)(n.span,{className:\"token operator\",children:\"=\"}),\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"new\"}),\" \",(0,e.jsx)(n.span,{className:\"token class-name\",children:\"cdk\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"aws_lambda\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),(0,e.jsx)(n.span,{className:\"token function\",children:\"CfnUrl\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"(\"}),(0,e.jsx)(n.span,{className:\"token keyword\",children:\"this\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),\" \",(0,e.jsx)(n.span,{className:\"token string\",children:'\"lambdaUrl\"'}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),\" \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"{\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" targetFunctionArn\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" myLambda\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"functionArn\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" authType\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" cdk\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"aws_lambda\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"FunctionUrlAuthType\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),(0,e.jsx)(n.span,{className:\"token constant\",children:\"NONE\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"}\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\")\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\";\"}),`\n`]}),(0,e.jsx)(n.span,{className:\"code-line\",children:`\n`}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"const\"}),\" lambdaPermission \",(0,e.jsx)(n.span,{className:\"token operator\",children:\"=\"}),\" \",(0,e.jsx)(n.span,{className:\"token keyword\",children:\"new\"}),\" \",(0,e.jsx)(n.span,{className:\"token class-name\",children:\"cdk\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),(0,e.jsx)(n.span,{className:\"token function\",children:\"CfnResource\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"(\"}),(0,e.jsx)(n.span,{className:\"token keyword\",children:\"this\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),\" \",(0,e.jsx)(n.span,{className:\"token string\",children:'\"lambdaPermission\"'}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),\" \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"{\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" type\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" \",(0,e.jsx)(n.span,{className:\"token string\",children:'\"AWS::Lambda::Permission\"'}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" properties\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"{\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" Action\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" \",(0,e.jsx)(n.span,{className:\"token string\",children:'\"lambda:InvokeFunctionUrl\"'}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" FunctionName\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" myLambda\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\".\"}),\"functionArn\",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" Principal\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" \",(0,e.jsx)(n.span,{className:\"token string\",children:'\"*\"'}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" FunctionUrlAuthType\",(0,e.jsx)(n.span,{className:\"token operator\",children:\":\"}),\" \",(0,e.jsx)(n.span,{className:\"token string\",children:'\"NONE\"'}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"}\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\",\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"}\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\")\"}),(0,e.jsx)(n.span,{className:\"token punctuation\",children:\";\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[\" \",(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"}\"}),`\n`]}),(0,e.jsxs)(n.span,{className:\"code-line\",children:[(0,e.jsx)(n.span,{className:\"token punctuation\",children:\"}\"}),`\n`]})]})}),`\n`,(0,e.jsxs)(n.h2,{id:\"pricing\",children:[(0,e.jsx)(n.a,{\"aria-hidden\":\"true\",tabIndex:\"-1\",href:\"#pricing\",children:(0,e.jsx)(n.span,{className:\"icon icon-link\"})}),\"Pricing\"]}),`\n`,(0,e.jsxs)(n.p,{children:[\"Lambda function URLs are included in AWS Lambda's pricing - there are no additional charges for using this feature (and you can save money on \",(0,e.jsx)(n.strong,{children:\"not\"}),\" using API Gateway)\"]}),`\n`,(0,e.jsxs)(n.h2,{id:\"limits\",children:[(0,e.jsx)(n.a,{\"aria-hidden\":\"true\",tabIndex:\"-1\",href:\"#limits\",children:(0,e.jsx)(n.span,{className:\"icon icon-link\"})}),\"Limits\"]}),`\n`,(0,e.jsx)(n.p,{children:\"Lambda function URLs share the same limits as AWS Lambda functions:\"}),`\n`,(0,e.jsxs)(n.ul,{children:[`\n`,(0,e.jsx)(n.li,{children:\"6 MB response and request payload size\"}),`\n`,(0,e.jsx)(n.li,{children:\"Default 1,000 up to tens of thousands TPS\"}),`\n`,(0,e.jsx)(n.li,{children:\"15-minute timeout\"}),`\n`]}),`\n`,(0,e.jsx)(n.p,{children:\"In short - there is no additional cost, no additional timeout and payload limits when choosing to use Lambda function URLs.\"}),`\n`,(0,e.jsxs)(n.p,{children:[\"Check out the \",(0,e.jsx)(n.a,{href:\"https://docs.aws.amazon.com/lambda/latest/dg/urls-auth.html\",children:\"official AWS docs to learn more\"}),\".\"]}),`\n`,(0,e.jsxs)(n.h2,{id:\"so-whats-the-difference-between-function-urls-and-api-gateway-are-function-urls-objectively-better\",children:[(0,e.jsx)(n.a,{\"aria-hidden\":\"true\",tabIndex:\"-1\",href:\"#so-whats-the-difference-between-function-urls-and-api-gateway-are-function-urls-objectively-better\",children:(0,e.jsx)(n.span,{className:\"icon icon-link\"})}),\"So, what's the difference between Function URLs and API Gateway? Are Function URLs objectively better?\"]}),`\n`,(0,e.jsx)(n.p,{children:\"Not exactly, there's always a tradeoff.\"}),`\n`,(0,e.jsxs)(n.table,{children:[(0,e.jsx)(n.thead,{children:(0,e.jsxs)(n.tr,{children:[(0,e.jsx)(n.th,{children:\"Feature\"}),(0,e.jsx)(n.th,{children:\"API Gateway REST APIs\"}),(0,e.jsx)(n.th,{children:\"Function URLs\"})]})}),(0,e.jsxs)(n.tbody,{children:[(0,e.jsxs)(n.tr,{children:[(0,e.jsx)(n.td,{children:\"HTTPS\"}),(0,e.jsx)(n.td,{children:\"Yes\"}),(0,e.jsx)(n.td,{children:\"Yes\"})]}),(0,e.jsxs)(n.tr,{children:[(0,e.jsx)(n.td,{children:\"Payload limit\"}),(0,e.jsx)(n.td,{children:\"6 MB (with AWS Lambda)\"}),(0,e.jsx)(n.td,{children:\"6 MB\"})]}),(0,e.jsxs)(n.tr,{children:[(0,e.jsx)(n.td,{children:\"Max timeout\"}),(0,e.jsx)(n.td,{children:\"29 seconds\"}),(0,e.jsx)(n.td,{children:\"Up to 15 minutes\"})]}),(0,e.jsxs)(n.tr,{children:[(0,e.jsx)(n.td,{children:\"SDK generation\"}),(0,e.jsx)(n.td,{children:\"Yes\"}),(0,e.jsx)(n.td,{children:\"No\"})]}),(0,e.jsxs)(n.tr,{children:[(0,e.jsx)(n.td,{children:\"Cost\"}),(0,e.jsx)(n.td,{children:\"from $3.50/million for first 333 million\"}),(0,e.jsx)(n.td,{children:\"Free\"})]}),(0,e.jsxs)(n.tr,{children:[(0,e.jsx)(n.td,{children:\"AWS WAF\"}),(0,e.jsx)(n.td,{children:\"Yes\"}),(0,e.jsx)(n.td,{children:\"No\"})]}),(0,e.jsxs)(n.tr,{children:[(0,e.jsx)(n.td,{children:\"Usage plans\"}),(0,e.jsx)(n.td,{children:\"Yes\"}),(0,e.jsx)(n.td,{children:\"No\"})]}),(0,e.jsxs)(n.tr,{children:[(0,e.jsx)(n.td,{children:\"Request/response validation and transformation\"}),(0,e.jsx)(n.td,{children:\"Yes\"}),(0,e.jsx)(n.td,{children:\"No\"})]})]})]}),`\n`,(0,e.jsx)(n.p,{children:(0,e.jsx)(n.a,{href:\"https://www.youtube.com/watch?v=B-Mz-HTSavM\",children:\"Source - AWS Summit SF 2022 - Best practices for building interactive applications with AWS Lambda (CON302)\"})}),`\n`,(0,e.jsx)(n.p,{children:\"Function URLs have a greatly extended timeout (up to 15 minutes) compared to API Gateway + Lambda, with the tradeoff of highly reduced security/usage limits capabilities.\"}),`\n`,(0,e.jsxs)(n.p,{children:[\"To quote \",(0,e.jsx)(n.a,{href:\"https://aws.amazon.com/blogs/aws/announcing-aws-lambda-function-urls-built-in-https-endpoints-for-single-function-microservices/\",children:\"Announcing AWS Lambda Function URLs\"}),\" blogpost:\"]}),`\n`,(0,e.jsxs)(n.blockquote,{children:[`\n`,(0,e.jsx)(n.p,{children:\"Function URLs are best for use cases where you must implement a single-function microservice with a public endpoint that doesn\\u2019t require the advanced functionality of API Gateway, such as request validation, throttling, custom authorizers, custom domain names, usage plans, or caching. [...] It is also the simplest way to invoke your Lambda functions during research and development without leaving the Lambda console or integrating additional services.\"}),`\n`]}),`\n`,(0,e.jsxs)(n.blockquote,{children:[`\n`,(0,e.jsx)(n.p,{children:\"Use API Gateway to take advantage of capabilities like JWT/custom authorizers, request/response validation and transformation, usage plans, built-in AWS WAF support, and so on.\"}),`\n`]}),`\n`,(0,e.jsxs)(n.p,{children:[\"Learn more in \",(0,e.jsx)(n.a,{href:\"https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html\",children:\"Lambda function URLs documentation\"}),\".\"]})]})}function g(a={}){let{wrapper:n}=a.components||{};return n?(0,e.jsx)(n,Object.assign({},a,{children:(0,e.jsx)(d,a)})):d(a)}var A=g;return y(L);})();\n;return Component;","frontmatter":{"slug":"guide-to-lambda-function-urls","date":"2022-08-23T00:00:00.000Z","title":"Guide to AWS Lambda Function URLs","tags":["AWS","Lambda","serverless"],"summary":"Learn how to create dedicated HTTP(S) endpoints for Lambda functions without an API Gateway","authors":["tlakomy"],"fileName":"guide-to-lambda-function-urls.mdx"}},"authors":[{"name":"Tomasz Łakomy","avatar":"/assets/blog/authors/tomasz.jpeg","twitter":"https://twitter.com/tlakomy","slug":["tlakomy"],"fileName":"tlakomy.md","date":null}],"prev":{"fileName":"aws-lambda-default-environment-variables.mdx","slug":"aws-lambda-default-environment-variables","date":"2022-06-06T00:00:00.000Z","title":"Guide to default AWS Lambda environment variables","tags":["AWS","Lambda"],"summary":"A walkthrough of the default AWS Lambda environment variables","authors":["tlakomy"]},"next":{"fileName":"http-keep-alive-lambda.mdx","slug":"http-keep-alive-lambda","date":"2022-08-28T00:00:00.000Z","title":"AWS Lambda optimization tip - reuse TCP connections in Node.js","draft":false,"tags":["AWS","Lambda","serverlesss"],"summary":"Learn how to optimize your Node.js AWS Lambda functions with a single environment variable","authors":["tlakomy"]}},"__N_SSG":true}