全部产品
Search
文档中心

API 网关:函数计算

更新时间:Dec 11, 2023

函数计算是一个事件驱动的服务(函数概述)。API 网关与函数计算对接,可以让您以 API 形式安全地对外开放您的函数,并且解决认证、流量控制、数据转换等问题。

1 功能简介

API网关目前支持两种形式的函数,HTTP函数事件函数

2 HTTP函数对接API网关

2.1 创建HTTP函数

在配置API网关前,需要先在函数计算中创建一个带有HTTP触发器的函数,可参考配置HTTP触发器并使用HTTP触发

2.2 添加API

说明

在API网关控制台上的详细操作步骤,详见快速入门中的 创建后端为函数计算的API。本文主要对需要注意的地方加以说明。

  • API分组。建议API分组与函数计算在相同的地域。

说明

如果函数计算与 API 不在同一地域,将通过公网访问您的函数计算服务,产生流量费用。若您对数据安全和网络延迟有较高要求,请选择API 与函数计算为同一地域。

  • 创建和定义API。在“定义API后端服务”步骤中,如下图所示:

后端服务类型:选择“函数计算”。

调用方式:选择“HTTP触发器”。

触发器路径:请使用函数计算控制台触发器页面中的路径;如果是同region调用,可以将触发器路径上的域名更换为内网地址。在函数计算控制台左侧栏单击服务及函数——单击服务名称进入——在函数管理中找到HTTP函数——单击函数名称,在触发器管理(URL) 里面找到内网访问地址。

后端请求path:可以自定义path,如果不需要自定义,请填写"/"。

HTTP Method:请选择后端函数计算支持的method, 如果多个请选择"any".

角色Arn:用于授权API网关访问函数计算服务。默认情况下,您需要按照API网关控制台上的操作引导,即可实现API网关访问相同账号下的函数计算。

2.3 使用其他账号的函数计算

API网关除了使用相同账号下的函数计算服务外,还可以使用其他账号下的函数计算服务。以A账号下的API网关需要使用B账号下的函数计算为例,介绍如何操作。

  1. B账号为A账号API网关的访问函数计算授权

    步骤1:使用B账号登录RAM控制台,创建RAM角色,参考创建可信实体为阿里云账号的RAM角色

    步骤2:为步骤1中创建的角色增加调用函数计算的授权。需要添加名为AliyunFCInvocationAccess的系统权限,参考在RAM角色管理页面为RAM角色授权

    步骤3:修改步骤1创建的角色的信任策略,参考 修改RAM角色的可信实体为阿里云账号。将A账号的AccountID(如123456789012****)添加到信任策略中,修改后的信任策略如下:

{
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "123456789012****@apigateway.aliyuncs.com"
        ]
      }
    }
  ],
  "Version": "1"
}

步骤4:B账号将步骤1创建的角色的Arn(了解 RAM角色基本概念)提供给A账号。

  1. A账号在API网关控制台中添加访问B账号的函数计算服务。其中触发路径内容为B账号下的函数计算服务的访问地址,角色Arn中填写B账号提供的角色Arn名称。

重要

当后端服务为HTTP函数时,客户端发送的Authorization参数值会被HTTP函数的Authorization覆盖,建议客户端更换参数名称。

3 事件函数对接API网关

3.1 创建事件触发函数

函数计算控制台配置API网关触发函数执行的流程可以参考配置API网关触发器

3.2 创建API

说明

在API网关控制台上的详细操作步骤,详见快速入门中的 创建后端为函数计算的API。本文主要对需要注意的地方加以说明。

  • API分组。建议API分组与函数计算在相同的地域。

说明

如果函数计算与 API 不在同一地域,将通过公网访问您的函数计算服务,产生流量费用。若您对数据安全和网络延迟有较高要求,请选择API 与函数计算为同一地域。

  • 创建API。在“定义API后端服务”步骤中,如下图所示:

image

函数类型:选择“事件”

服务名称函数名称:请根据实际的函数计算名称填写。

3.2.事件函数对接API网关的格式要求

API 网关调用函数计算的事件函数时,会将 API 的相关数据转换为 Map 形式传给函数计算服务。函数计算服务处理后,按照下图中 Output Format 的格式返回 statusCode、headers、body 等相关数据。API 网关再将函数计算返回的内容映射到 statusCode、header、body等位置返回给客户端。

API 网关向函数计算传入参数格式:

当以函数计算作为 API 网关的后端服务时,API 网关会把请求参数通过一个固定的 Map 结构传给函数计算的入参 event。函数计算通过如下结构去获取需要的参数,然后进行处理。

{
        "path":"api request path",
        "httpMethod":"request method name",
        "headers":{all headers,including system headers},
        "queryParameters":{query parameters},
        "pathParameters":{path parameters},
        "body":"string of request payload",
        "isBase64Encoded":"true|false, indicate if the body is Base64-encode"
}
  • 如果 "isBase64Encoded" 的值为 "true",表示 API 网关传给函数计算的 body 内容已进行 Base64 编码。函数计算需要先对 body 内容进行 Base64 解码后再处理。

  • 如果"isBase64Encoded" 的值为 "false",表示 API 网关没有对 body 内容进行 Base64 编码。

函数计算的返回参数格式:

函数计算需要将输出内容通过如下 JSON 格式返回给 API 网关,以便 API 网关解析。

{
        "isBase64Encoded":true|false,
        "statusCode":httpStatusCode,
        "headers":{response headers},
        "body":"..."
}
  • 当 body 内容为二进制编码时,需在函数计算中对 body 内容进行 Base64 编码,设置"isBase64Encoded" 的值为 "true"。如果 body 内容无需 Base64 编码,"isBase64Encoded" 的值为 "false"。API 网关会对 "isBase64Encoded" 的值为 "true" 的 body 内容进行 Base64 解码后,再返回给客户端。

  • 在 Node.js 环境中,函数计算根据不同的情况设置 callback。

    • 返回成功请求: callback(null,{"statusCode":200,"body":"..."})。

    • 返回异常:callback(new Error('internal server error'),null)。

    • 返回客户端错误: callback(null,{"statusCode":400,"body":"param error"})。

  • 如果函数计算返回不符合格式要求的返回结果,API 网关将返回 503 Service Unavailable 给客户端。

3.3 事件函数调用示例

以下提供三个示例,分别为:事件函数代码示例、API 请求示例、和 API 网关返回示例。

3.3.1 事件函数代码示例

在函数计算的代码执行页面配置的代码示例。

module.exports.handler = function(event, context, callback) {
    var responseCode = 200;
    console.log("request: " + JSON.stringify(event.toString()));
    //将event转化为JSON对象
    event=JSON.parse(event.toString());
    var isBase64Encoded=false;
        //根据用户输入的statusCode返回,可用于测试不同statusCode的情况
    if (event.queryParameters !== null && event.queryParameters !== undefined) {
        if (event.queryParameters.httpStatus !== undefined && event.queryParameters.httpStatus !== null && event.queryParameters.httpStatus !== "") {
            console.log("Received http status: " + event.queryParameters.httpStatus);
            responseCode = event.queryParameters.httpStatus;
        }
    }
    //如果body是Base64编码的,FC中需要对body内容进行解码
    if(event.body!==null&&event.body!==undefined){
            if(event.isBase64Encoded!==null&&event.isBase64Encoded!==undefined&&event.isBase64Encoded){
                    event.body=new Buffer(event.body,'base64').toString();
            }
    }
    //input是API网关给FC的输入内容
    var responseBody = {
        message: "Hello World!",
        input: event
    };
        //对body内容进行Base64编码,可根据需要处理
    var base64EncodeStr=new Buffer(JSON.stringify(responseBody)).toString('base64');
        //FC给API网关返回的格式,须如下所示。isBase64Encoded根据body是否Base64编码情况设置
    var response = {
                isBase64Encoded:true,
                statusCode: responseCode,
                headers: {
                "x-custom-header" : "header value"
                },
                body: base64EncodeStr
    };
    console.log("response: " + JSON.stringify(response));
    callback(null, response);
};        

3.3.2 事件函数请求示例

以 POST 形式请求 path 为如下的 API:

/fc/test/invoke/[type]        

发起请求如下:

POST http://test.alicloudapi.com/fc/test/invoke/test?param1=aaa&param2=bbb
"X-Ca-Signature-Headers":"X-Ca-Timestamp,X-Ca-Version,X-Ca-Key,X-Ca-Stage",
"X-Ca-Signature":"TnoBldxxRHrFferGlzzkGcQsaezK+ZzySloKqCOsv2U=",
"X-Ca-Stage":"RELEASE",
"X-Ca-Timestamp":"1496652763510",
"Content-Type":"application/x-www-form-urlencoded; charset=utf-8",
"X-Ca-Version":"1",
"User-Agent":"Apache-HttpClient\/4.1.2 (java 1.6)",
"Host":"test.alicloudapi.com",
"X-Ca-Key":"testKey",
"Date":"Mon, 05 Jun 2017 08:52:43 GMT","Accept":"application/json",
"headerParam":"testHeader"
{"bodyParam":"testBody"}        

3.3.3 API网关返回示例

200
Date: Mon, 05 Jun 2017 08:52:43 GMT
Content-Type: application/json; charset=UTF-8
Content-Length: 429
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,HEAD,OPTIONS , PATCH
Access-Control-Allow-Headers: X-Requested-With, X-Sequence,X-Ca-Key,X-Ca-Secret,X-Ca-Version,X-Ca-Timestamp,X-Ca-Nonce,X-Ca-API-Key,X-Ca-Stage,X-Ca-Client-DeviceId,X-Ca-Client-AppId,X-Ca-Signature,X-Ca-Signature-Headers,X-Forwarded-For,X-Ca-Date,X-Ca-Request-Mode,Authorization,Content-Type,Accept,Accept-Ranges,Cache-Control,Range,Content-MD5
Access-Control-Max-Age: 172800
X-Ca-Request-Id: 16E9D4B5-3A1C-445A-BEF1-4AD8E31434EC
x-custom-header: header value
{"message":"Hello World!","input":{"body":"{\"bodyParam\":\"testBody\"}","headers":{"X-Ca-Api-Gateway":"16E9D4B5-3A1C-445A-BEF1-4AD8E31434EC","headerParam":"testHeader","X-Forwarded-For":"100.81.146.152","Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"},"httpMethod":"POST","isBase64Encoded":false,"path":"/fc/test/invoke/test","pathParameters":{"type":"test"},"queryParameters":{"param1":"aaa","param2":"bbb"}}}
        

4 常见问题

4.1 为什么我无法录入我已有的函数?

请确认您输入的函数计算的服务名称和函数名称是否与您在函数计算控制台创建的服务和函数的名称一致。

4.2 使用函数计算作为API后端服务时,API网关到后端服务是否可以走内网?

当选择事件函数时,API网关和函数计算在同一region时,默认走内网。