配置HTTP触发器并使用HTTP触发

函数计算支持HTTP触发器,配置HTTP触发器的函数可以通过HTTP请求被触发执行。此时函数可以看做一个Web Server,对HTTP请求进行处理,并将处理结果返回给调用端。本文介绍如何在函数计算控制台配置HTTP触发器并使用HTTP请求触发。

前提条件

创建服务

步骤一:创建触发器

说明

HTTP触发器与其他类型的触发器不同,当您创建HTTP类型的函数后,系统会默认为该函数创建一个HTTP触发器,而对于其他类型的触发器,需根据触发源手动创建对应的触发器。

  1. 登录函数计算控制台,在左侧导航栏,单击服务及函数
  2. 在顶部菜单栏,选择地域,然后在服务列表页面,单击目标服务。
  3. 函数管理页面,单击创建函数
  4. 创建函数页面,选择使用内置运行时创建,然后根据需要,填写函数相关信息。

    需设置的配置项说明如下,其余配置项的值保持默认值即可。更多信息,请参见创建函数

    配置项

    解释说明

    基本设置

    函数名称

    设置您要创建的函数的名称。

    请求处理程序类型

    选择处理 HTTP 请求

    触发器配置(可选)

    名称

    设置您要创建的触发器的名称。

    请求方法

    指定可以通过哪些方法触发该HTTP触发器。

    禁用公网访问 URL

    默认选择,即允许公网域名访问该触发器。

    如果选择,创建的HTTP触发器将不提供默认的公网域名。此时,如果通过公网域名来调用函数,将会提示错误access denied due to function internet URL is disabled。通过自定义域名的访问,则不受影响。

    认证方式

    选择函数计算对HTTP请求的认证方式。取值说明如下:

    • 无需认证:无需对HTTP请求进行身份认证,支持匿名访问,任何人可发起HTTP请求调用您的函数。

    • 签名认证:需要对HTTP请求进行身份认证。关于签名认证的示例代码,请参见签名认证

    • JWT 认证:需要对HTTP请求进行JWT认证。更多信息,请参见为HTTP触发器配置JWT认证鉴权

    您可以根据需要对已创建的HTTP触发器的配置项进行修改,包括版本或别名请求方法禁用公网访问 URL认证方式

步骤二:编写并部署代码

完成创建HTTP触发器后,您可以开始编写函数代码。

在函数详情页面,单击函数代码页签,在代码编辑器中编写代码,然后单击部署代码

代码示例如下。

var getRawBody = require('raw-body')
module.exports.handler = function (request, response, context) {
    // get request info
    getRawBody(request, function (err, data) {
        var params = {
            path: request.path,
            queries: request.queries,
            headers: request.headers,
            method: request.method,
            body: data,
            url: request.url,
            clientIP: request.clientIP,
        }
        // you can deal with your own logic here
        // set response
        var respBody = new Buffer.from(JSON.stringify(params));
        // var respBody = new Buffer( )
        response.setStatusCode(200)
        response.setHeader('content-type', 'application/json')
        response.send(respBody)
    })
};
# -*- coding: utf-8 -*-
import json
HELLO_WORLD = b"Hello world!\n"
def handler(environ, start_response):
    request_uri = environ['fc.request_uri']
    response_body = {
      'uri':environ['fc.request_uri'],
      'method':environ['REQUEST_METHOD']
    }
    # do something here
    status = '200 OK'
    response_headers = [('Content-type', 'text/json')]
    start_response(status, response_headers)
    # Python2
    return [json.dumps(response_body)]
    # Python3 tips: When using Python3, the str and bytes types cannot be mixed.
    # Use str.encode() to go from str to bytes
    # return [json.dumps(response_body).encode()]
<?php
use RingCentral\Psr7\Response;
function handler($request, $context): Response{
    /*
    $body       = $request->getBody()->getContents();
    $queries    = $request->getQueryParams();
    $method     = $request->getMethod();
    $headers    = $request->getHeaders();
    $path       = $request->getAttribute("path");
    $requestURI = $request->getAttribute("requestURI");
    $clientIP   = $request->getAttribute("clientIP");
    */
    return new Response(
        200,
        array(
            "custom_header1" => "v1",
            "custom_header2" => ["v2", "v3"],
        ),
        "hello world"
    );
}
重要

对于异步调用,请在函数链路中做好异步结果回调处理。具体操作,请参见结果回调

步骤三:测试函数

方式一:使用控制台测试函数

  • 同步调用

    在函数详情页面,单击函数代码页签,然后单击测试函数

  • 异步调用

    在函数详情页面,单击测试函数页签,勾选我想通过异步的方式进行调用,然后单击测试函数

方式二:使用浏览器测试函数

将HTTP触发器URL输入浏览器地址栏,按回车键执行。

执行完成后,浏览器中会返回执行结果文件。

HTTP触发器URL的获取方式如下所示。

  • 针对新建HTTP触发器,推荐您使用函数计算为新建HTTP触发器分配的子域名作为HTTP触发器URL。

    子域名格式如下。

    <subdomain>.<region_id>.fcapp.run/[action?queries] 

    示例如下。

    funcname-svcname-khljsjksld.cn-shanghai.fcapp.run/action?hello=world
    说明

    您也可以按照存量HTTP触发器URL组装规则组装HTTP触发器URL。函数计算推荐您使用函数计算为新建HTTP触发器分配的子域名subdomain作为HTTP触发器URL进行函数测试,能有效避免404报错,也能避免代码中耦合函数计算的服务名称和函数名称,增强代码的可移植性。关于404报错的更多信息,请参见当我使用浏览器或cURL方式访问函数时出现404怎么办?

  • 针对存量HTTP触发器,您可以按照组装规则组装HTTP触发器URL。

    组装规则如下。

    <account_id>.<region_id>.fc.aliyuncs.com/<version>/proxy/<serviceName>/<functionName>/[action?queries]            

    示例如下。

    164901546557****.cn-shanghai.fc.aliyuncs.com/2016-08-15/proxy/serviceName/functionName/action?hello=world           

    参数说明如下。

    参数

    说明

    account_id

    阿里云账号ID。

    您可以在安全设置中获取您的账号ID。如果您是RAM用户,将鼠标移至控制台右上角的头像处,可以看到您的阿里云账号ID。

    region_id

    函数计算服务所在的地域。

    version

    函数计算的API版本。

    serviceName

    服务名称。

    functionName

    函数名称。

    action

    自定义的请求路径。

    queries

    查询参数。

方式三:使用cURL测试函数

  • 同步调用

    在命令行执行如下命令,执行完成后会返回执行结果。

    curl -v https://http-***.cn-shenzhen.fcapp.run/$path
  • 异步调用

    在命令行执行如下命令,执行完成后会返回函数计算接收请求的结果。其中状态码202表示请求成功,其余表示请求出现错误,关于错误码的解释,请参见常见问题(错误排查)

    curl -v -H "X-Fc-Invocation-Type: Async" https://http-***.cn-shenzhen.fcapp.run/$path

(可选)使用API网关保护HTTP函数

默认情况下,函数计算不会对HTTP请求进行身份验证,支持匿名访问HTTP函数,即任何人都可以发送HTTP请求调用您的函数。为防止非法用户访问您的函数,引起不必要的资源浪费或安全隐患,您可以开启身份认证的同时将HTTP函数与API网关进行对接,利用API网关的IP访问控制插件、JWT认证插件或BasicAuth插件等保护您的HTTP函数。

  1. 函数计算控制台找到目标HTTP函数,在函数详情页面单击触发器管理页签,然后编辑HTTP触发器,是否需要认证选择为

  2. 登录API网关控制台,切换至HTTP函数所在地域。

  3. 创建分组。具体操作,请参见创建分组

  4. 将您的域名通过CNAME方式解析到API网关提供的二级域名上。具体操作,请参见CNAME绑定域名

  5. 创建API。

    主要配置项设置如下,其余配置项下的设置选择默认值或者根据实际情况填写即可。更多信息,请参见创建 API

    • 安全认证:选择无认证,后续会使用插件进行认证。

    • 请求Path:填写根目录/,然后选中匹配所有子路径

    • HTTP Method:选择ANY

    • 入参请求模式:选择入参透传

    • 后端服务类型:选择函数计算

    • 函数类型:选择HTTP函数

    • 触发器路径:填写函数计算的HTTP函数的内网访问地址

    • ContentType:选择透传客户端ContentType头

  6. 发布API。单击已创建的API右侧操作列的发布,选择线上环境,然后单击发布

  7. 创建一个类型为后端签名的插件,keyvalue分别配置为您的阿里云账号的AccessKey IDAccessKey Secret。然后绑定您刚才创建的API。具体操作,请参见插件概述

完成以上步骤后,您可以通过自己的域名访问HTTP函数。您还可以创建以下插件,并将其绑定到您的API,保护您的HTTP函数。

常见问题

为什么HTTP函数无法执行?

为什么函数无法结束?

请检查是否调用返回函数。

  • Node.js需调用response.send()

  • Python需调用return

  • PHP需调用return new Response()

  • Java需调用HttpServletResponse

  • C#需调用return

  • Custom Runtime以各语言示例为准。

错误排查

错误主要分为以下两种。

  • 请求错误是指发送的Request不符合标准,在Response里报错状态码为4xx。

  • 函数错误即编写的函数有问题,会报5xx状态码。

下表描述请求错误和函数错误可能出现的场景,以便您迅速排查问题。

错误类型

X-Fc-Error-Type

HTTP状态码

原因分析

是否计费

请求错误

FcCommonError

400

您的请求超过Request限制项的限制。更多信息,请参见HTTP触发器概述

FcCommonError

400

调用需要身份认证的函数的Request没有传入Date信息或Authorization信息。

FcCommonError

403

调用需要身份认证的函数的Request的签名错误,即Authorization不正确。由于Date参与签名计算,且超过15 min,签名失效,一种常见的原因是使用需要访问认证的HTTP触发器,Request header中发送的Date距当前时间超过15 min,导致签名失效。

FcCommonError

403

您的Request请求使用HTTP触发器中未配置的请求方法。例如,HTTP触发器中的请求方法只配置GET方法,却发送POST方法的HTTP请求。

FcCommonError

404

向没有设置HTTP触发器的函数发送HTTP请求。

用户流控

FcCommonError

429

用户被流控,可减小并发量或者联系函数计算开发团队提高并发度。

函数错误

UnhandledInvocationError

502

函数的返回值超过Response限制项的限制。更多信息,请参见HTTP触发器概述

UnhandledInvocationError

502

函数代码有语法错误或者异常。

UnhandledInvocationError

502

向未使用HTTP入口函数的函数发送HTTP请求。

系统错误

FcCommonError

500

函数计算系统错误,可重试解决。

系统流控

FcCommonError

503

函数计算系统流控。可用指数退避方式重试。

如果问题还未能解决,请加入钉钉用户群(钉钉群号:11721331),联系函数计算工程师即时沟通处理。

更多信息

除了函数计算控制台,您还可通过以下方式配置触发器:

  • 通过Serverless Devs工具配置触发器。更多操作,请参见Serverless Devs

  • 通过SDK配置触发器。更多操作,请参见SDK列表

如需对创建的触发器进行修改或删除,具体操作,请参见触发器管理