

# 调用 Lambda 函数 URL
<a name="urls-invocation"></a>

函数 URL 是 Lambda 函数的专用 HTTP(S) 端点。您可以通过 Lambda 控制台或 Lambda API 创建和配置函数 URL。

**提示**  
Lambda 提供了两种方法来通过 HTTP 端点调用函数：函数 URL 和 Amazon API Gateway。如果您不确定哪种方法最适合您的应用场景，请参阅[选择使用 HTTP 请求调用 Lambda 函数的方法](furls-http-invoke-decision.md)。

创建函数 URL 时，Lambda 会自动为您生成唯一的 URL 端点。创建函数 URL 后，其 URL 端点永远不会改变。函数 URL 的端点具有以下格式：

```
https://<url-id>.lambda-url.<region>.on.aws
```

**注意**  
以下 AWS 区域不支持函数 URL：亚太地区（海得拉巴）(`ap-south-2`)、亚太地区（墨尔本）(`ap-southeast-4`)、亚太地区（马来西亚）(`ap-southeast-5`)、亚太地区（新西兰）(`ap-southeast-6`)、亚太地区（泰国）(`ap-southeast-7`)、亚太地区（台北）(`ap-east-2`)、加拿大西部（卡尔加里）(`ca-west-1`)、欧洲（西班牙）(`eu-south-2`)、欧洲（苏黎世）(`eu-central-2`)、以色列（特拉维夫）(`il-central-1`) 和中东（阿联酋）(`me-central-1`)。

函数 URL 启用了双堆栈，支持 IPv4 和 IPv6。配置函数 URL 后，可以通过 Web 浏览器、curl、Postman 或任何 HTTP 客户端通过其 HTTP(S) 端点调用函数。要调用函数 URL，您必须具有 `lambda:InvokeFunctionUrl` 和 `lambda:InvokeFunction` 权限。有关更多信息，请参阅[访问控制](urls-auth.md)。

**Topics**
+ [函数 URL 调用基础](#urls-invocation-basics)
+ [请求和响应有效负载](#urls-payloads)

## 函数 URL 调用基础
<a name="urls-invocation-basics"></a>

如果函数 URL 使用 `AWS_IAM` 身份验证类型，则必须使用 [AWS 签名版本 4 (SigV4)](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html) 对每个 HTTP 请求进行签名。[Postman](https://quickstarts.postman.com/guide/aws/index.html?index=..%2F..index#2) 等工具提供了内置的方法使用 SigV4 对请求进行签名。

如果不使用工具向函数 URL 对 HTTP 请求进行签名，则必须使用 SigV4 手动对每个请求进行签名。当函数 URL 收到请求时，Lambda 还会计算 SigV4 签名。Lambda 仅在签名匹配时处理请求。有关如何使用 SigV4 手动对请求进行签名的说明，请参阅*《Amazon Web Services 一般参考 指南》*中的[利用签名版本 4 对 AWS 请求进行签名](https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html)。

如果函数 URL 使用 `NONE` 身份验证类型，则不必使用 SigV4 对请求进行签名。您可以使用 Web 浏览器、curl、Postman 或任何 HTTP 客户端来调用函数。

要测试对函数的简单 `GET` 请求，请使用 Web 浏览器。例如，如果您的函数 URL 为 `https://abcdefg.lambda-url.us-east-1.on.aws`，并且包含一个字符串参数 `message`，那么您的请求 URL 可能如下所示：

```
https://abcdefg.lambda-url.us-east-1.on.aws/?message=HelloWorld
```

要测试其他 HTTP 请求，例如 `POST` 请求，可以使用 curl 之类的工具。例如，如果希望在对函数 URL 的 `POST` 请求中包含一些 JSON 数据，可以使用以下 curl 命令：

```
curl -v 'https://abcdefg.lambda-url.us-east-1.on.aws/?message=HelloWorld' \
-H 'content-type: application/json' \
-d '{ "example": "test" }'
```

## 请求和响应有效负载
<a name="urls-payloads"></a>

当客户端调用函数 URL 时，Lambda 会将请求映射到事件对象，然后再将其传递给函数。然后，函数的响应将映射到一个 HTTP 响应，Lambda 会通过函数 URL 将该响应发送回客户端。

请求和响应事件格式遵循与 [Amazon API Gateway 有效负载格式版本 2.0](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.proxy-format) 相同的模式。

### 请求有效负载格式
<a name="urls-request-payload"></a>

请求有效负载具有以下结构：

```
{
  "version": "2.0",
  "routeKey": "$default",
  "rawPath": "/my/path",
  "rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
  "cookies": [
    "cookie1",
    "cookie2"
  ],
  "headers": {
    "header1": "value1",
    "header2": "value1,value2"
  },
  "queryStringParameters": {
    "parameter1": "value1,value2",
    "parameter2": "value"
  },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "<urlid>",
    "authentication": null,
    "authorizer": {
        "iam": {
                "accessKey": "AKIA...",
                "accountId": "111122223333",
                "callerId": "AIDA...",
                "cognitoIdentity": null,
                "principalOrgId": null,
                "userArn": "arn:aws:iam::111122223333:user/example-user",
                "userId": "AIDA..."
        }
    },
    "domainName": "<url-id>.lambda-url.us-west-2.on.aws",
    "domainPrefix": "<url-id>",
    "http": {
      "method": "POST",
      "path": "/my/path",
      "protocol": "HTTP/1.1",
      "sourceIp": "123.123.123.123",
      "userAgent": "agent"
    },
    "requestId": "id",
    "routeKey": "$default",
    "stage": "$default",
    "time": "12/Mar/2020:19:03:58 +0000",
    "timeEpoch": 1583348638390
  },
  "body": "Hello from client!",
  "pathParameters": null,
  "isBase64Encoded": false,
  "stageVariables": null
}
```


| 参数 | 描述 | 示例 | 
| --- | --- | --- | 
|  `version`  |  此事件的有效负载格式版本。Lambda 函数 URL 目前支持[有效负载格式版本 2.0](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.proxy-format)。  |  `2.0`  | 
|  `routeKey`  |  函数 URL 不使用此参数。Lambda 将其设置为 `$default`，作为占位符。  |  `$default`  | 
|  `rawPath`  |  请求路径。例如，如果请求 URL 为 `https://{url-id}.lambda-url.{region}.on.aws/example/test/demo`，则原始路径值为 `/example/test/demo`。  |  `/example/test/demo`  | 
|  `rawQueryString`  |  包含请求的查询字符串参数的原始字符串。支持的字符包括 `a-z`、`A-Z`、`0-9`、`.`、`_`、`-`、`%`、`&`、`=` 和 `+`。  |  `"?parameter1=value1&parameter2=value2"`  | 
|  `cookies`  |  数组包含发送的部分请求的所有 Cookie。  |  `["Cookie_1=Value_1", "Cookie_2=Value_2"]`  | 
|  `headers`  |  请求标头的列表，以键值对的形式显示。  |  `{"header1": "value1", "header2": "value2"}`  | 
|  `queryStringParameters`  |  请求的查询参数。例如，如果请求 URL 为 `https://{url-id}.lambda-url.{region}.on.aws/example?name=Jane`，则 `queryStringParameters` 值是一个 JSON 对象，其键为 `name`，值为 `Jane`。  |  `{"name": "Jane"}`  | 
|  `requestContext`  |  一个包含有关请求的附加信息的对象，例如 `requestId`、请求的时间以及通过 AWS Identity and Access Management (IAM) 授权的调用者身份。  |   | 
|  `requestContext.accountId`  |  函数拥有者的 AWS 账户 ID。  |  `"123456789012"`  | 
|  `requestContext.apiId`  |  函数 URL 的 ID。  |  `"33anwqw8fj"`  | 
|  `requestContext.authentication`  |  函数 URL 不使用此参数。Lambda 会将其设置为 `null`。  |  `null`  | 
|  `requestContext.authorizer`  |  对象包含有关调用者身份的信息（如果函数 URL 使用 `AWS_IAM` 身份验证类型）。否则，Lambda 会将其设置为 `null`。  |   | 
|  `requestContext.authorizer.iam.accessKey`  |  调用者身份的访问密钥。  |  `"AKIAIOSFODNN7EXAMPLE"`  | 
|  `requestContext.authorizer.iam.accountId`  |  调用者身份的 AWS 账户 ID。  |  `"111122223333"`  | 
|  `requestContext.authorizer.iam.callerId`  |  调用者的 ID（用户 ID）。  |  `"AIDACKCEVSQ6C2EXAMPLE"`  | 
|  `requestContext.authorizer.iam.cognitoIdentity`  |  函数 URL 不使用此参数。Lambda 会将其设置为 `null`，或将其从 JSON 中排除。  |  `null`  | 
|  `requestContext.authorizer.iam.principalOrgId`  |  与调用者身份关联的主体企业 ID。  |  `"AIDACKCEVSQORGEXAMPLE"`  | 
|  `requestContext.authorizer.iam.userArn`  |  调用者身份的用户 Amazon 资源名称（ARN）。  |  `"arn:aws:iam::111122223333:user/example-user"`  | 
|  `requestContext.authorizer.iam.userId`  |  调用者身份的用户 ID。  |  `"AIDACOSFODNN7EXAMPLE2"`  | 
|  `requestContext.domainName`  |  函数 URL 的域名。  |  `"<url-id>.lambda-url.us-west-2.on.aws"`  | 
|  `requestContext.domainPrefix`  |  函数 URL 的域前缀。  |  `"<url-id>"`  | 
|  `requestContext.http`  |  包含有关 HTTP 请求的详细信息的对象。  |   | 
|  `requestContext.http.method`  |  此请求中使用的 HTTP 方法。有效值包括 `GET`、`POST`、`PUT`、`HEAD`、`OPTIONS`、`PATCH` 和 `DELETE`。  |  `GET`  | 
|  `requestContext.http.path`  |  请求路径。例如，如果请求 URL 为 `https://{url-id}.lambda-url.{region}.on.aws/example/test/demo`，则路径值为 `/example/test/demo`。  |  `/example/test/demo`  | 
|  `requestContext.http.protocol`  |  请求的协议。  |  `HTTP/1.1`  | 
|  `requestContext.http.sourceIp`  |  发出请求的即时 TCP 连接的源 IP 地址。  |  `123.123.123.123`  | 
|  `requestContext.http.userAgent`  |  用户代理请求标头值。  |  `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Gecko/20100101 Firefox/42.0`  | 
|  `requestContext.requestId`  |  调用请求的 ID。可以使用此 ID 跟踪与函数相关的调用日志。  |  `e1506fd5-9e7b-434f-bd42-4f8fa224b599`  | 
|  `requestContext.routeKey`  |  函数 URL 不使用此参数。Lambda 将其设置为 `$default`，作为占位符。  |  `$default`  | 
|  `requestContext.stage`  |  函数 URL 不使用此参数。Lambda 将其设置为 `$default`，作为占位符。  |  `$default`  | 
|  `requestContext.time`  |  请求的时间戳。  |  `"07/Sep/2021:22:50:22 +0000"`  | 
|  `requestContext.timeEpoch`  |  请求的时间戳，用 Unix epoch 时间表示。  |  `"1631055022677"`  | 
|  `body`  |  请求的正文。如果请求的内容类型为二进制，则正文为 base64 编码。  |  `{"key1": "value1", "key2": "value2"}`  | 
|  `pathParameters`  |  函数 URL 不使用此参数。Lambda 会将其设置为 `null`，或将其从 JSON 中排除。  |  `null`  | 
|  `isBase64Encoded`  |  如果正文为二进制有效负载，并且为 base64 编码，则为 `TRUE`。否则为 `FALSE`。  |  `FALSE`  | 
|  `stageVariables`  |  函数 URL 不使用此参数。Lambda 会将其设置为 `null`，或将其从 JSON 中排除。  |  `null`  | 

### 响应有效负载格式
<a name="urls-response-payload"></a>

当函数返回响应时，Lambda 会解析响应并将其转换为 HTTP 响应。函数响应有效负载的格式如下：

```
{
   "statusCode": 201,
    "headers": {
        "Content-Type": "application/json",
        "My-Custom-Header": "Custom Value"
    },
    "body": "{ \"message\": \"Hello, world!\" }",
    "cookies": [
        "Cookie_1=Value1; Expires=21 Oct 2021 07:48 GMT",
        "Cookie_2=Value2; Max-Age=78000"
    ],
    "isBase64Encoded": false
}
```

Lambda 会为您推断响应格式。如果您的函数返回有效的 JSON 并且没有返回 `statusCode`，Lambda 会做出以下假设：
+ `statusCode`is(`200` )
**注意**  
有效的 `statusCode` 在 100 至 599 范围内。
+ `content-type`is(`application/json` )
+ `body` 是函数响应。
+ `isBase64Encoded`is(`false` )

以下示例显示了 Lambda 函数的输出如何映射到响应有效负载，以及响应有效负载如何映射到最终 HTTP 响应。当客户端调用函数 URL 时，就会看到 HTTP 响应。

**字符串响应的输出示例**


| Lambda 函数输出 | 解释响应输出 | HTTP 响应（客户端看到的内容） | 
| --- | --- | --- | 
|  <pre>"Hello, world!"</pre>  |  <pre>{<br />  "statusCode": 200,<br />  "body": "Hello, world!",<br />  "headers": {<br />    "content-type": "application/json"<br />  },<br />  "isBase64Encoded": false<br />}</pre>  |  <pre>HTTP/2 200<br />date: Wed, 08 Sep 2021 18:02:24 GMT<br />content-type: application/json<br />content-length: 15<br /><br />"Hello, world!"</pre>  | 

**JSON 响应的输出示例**


| Lambda 函数输出 | 解释响应输出 | HTTP 响应（客户端看到的内容） | 
| --- | --- | --- | 
|  <pre>{<br />  "message": "Hello, world!"<br />}</pre>  |  <pre>{<br />  "statusCode": 200,<br />  "body": {<br />    "message": "Hello, world!"<br />  },<br />  "headers": {<br />    "content-type": "application/json"<br />  },<br />  "isBase64Encoded": false<br />}</pre>  |  <pre>HTTP/2 200<br />date: Wed, 08 Sep 2021 18:02:24 GMT<br />content-type: application/json<br />content-length: 34<br /><br />{<br />  "message": "Hello, world!"<br />}</pre>  | 

**自定义响应的输出示例**


| Lambda 函数输出 | 解释响应输出 | HTTP 响应（客户端看到的内容） | 
| --- | --- | --- | 
|  <pre>{<br />   "statusCode": 201,<br />    "headers": {<br />        "Content-Type": "application/json",<br />        "My-Custom-Header": "Custom Value"<br />    },<br />    "body": JSON.stringify({<br />        "message": "Hello, world!"<br />    }),<br />    "isBase64Encoded": false<br />}</pre>  |  <pre>{<br />   "statusCode": 201,<br />    "headers": {<br />        "Content-Type": "application/json",<br />        "My-Custom-Header": "Custom Value"<br />    },<br />    "body": JSON.stringify({<br />        "message": "Hello, world!"<br />    }),<br />    "isBase64Encoded": false<br />}</pre>  |  <pre>HTTP/2 201<br />date: Wed, 08 Sep 2021 18:02:24 GMT<br />content-type: application/json<br />content-length: 27<br />my-custom-header: Custom Value<br /><br />{<br />  "message": "Hello, world!"<br />}</pre>  | 

### Cookie
<a name="urls-cookies"></a>

要从函数返回 Cookie，请不要手动添加 `set-cookie` 标头。相反，请在响应有效负载对象中包含 Cookie。Lambda 会自动进行解释，并将其作为 `set-cookie` 标头添加到 HTTP 响应中，如下例所示。


| Lambda 函数输出 | HTTP 响应（客户端看到的内容） | 
| --- | --- | 
|  <pre>{<br />   "statusCode": 201,<br />    "headers": {<br />        "Content-Type": "application/json",<br />        "My-Custom-Header": "Custom Value"<br />    },<br />    "body": JSON.stringify({<br />        "message": "Hello, world!"<br />    }),<br />    "cookies": [<br />        "Cookie_1=Value1; Expires=21 Oct 2021 07:48 GMT",<br />        "Cookie_2=Value2; Max-Age=78000"<br />    ],<br />    "isBase64Encoded": false<br />}</pre>  |  <pre>HTTP/2 201<br />date: Wed, 08 Sep 2021 18:02:24 GMT<br />content-type: application/json<br />content-length: 27<br />my-custom-header: Custom Value<br />set-cookie: Cookie_1=Value2; Expires=21 Oct 2021 07:48 GMT<br />set-cookie: Cookie_2=Value2; Max-Age=78000<br /><br />{<br />  "message": "Hello, world!"<br />}</pre>  | 