全部产品
云市场

HTTP 触发器

更新时间:2019-08-20 11:44:14

注意:

1. 设置 HTTP 触发器的函数接口与普通函数接口不同,详细信息请参考 HTTP 触发器接口形式

HTTP 触发器是众多函数计算触发器中的一种,通过发送 HTTP 请求触发函数执行。主要适用于快速构建 Web 服务等场景。HTTP 触发器支持 HEAD、POST、PUT、GET 和 DELETE 方式触发函数。

相对与上手门槛高的 API 网关 触发器,HTTP 触发器有如下优点:

  • 简化学习成本和调试过程,帮助您快速使用函数计算实现 Web Service 和 API。
  • 您可以选择自己熟悉的 HTTP 测试工具验证函数计算端的功能和性能。
  • 减少请求处理环节,FC HTTP 触发器支持更高效的请求/响应格式,不需要 encode/decode 成 json,性能更优。
  • 方便对接其他支持 Webhook 回调的服务,例如 CDN 回源,MNS 等。

您可以同通过 绑定自定义域名 来为 HTTP 函数映射不同的 HTTP 访问路径。除此外还可以使用 API 网关,后端服务类型选择 HTTP 服务,设置 HTTP 函数为后端服务地址,达到类似功能的目的。

本文介绍了以下 HTTP 触发器相关内容:

使用限制

  • 函数一旦设置 HTTP 触发器后不能设置其他类型触发器。
  • 每个函数只能创建一个 HTTP 触发器。
  • 在使用 版本管理 的前提下,每个(版本或别名,函数)的组合只能创建一个HTTP触发器。
    • 例如,别名1指向版本1,(版本1,函数1)可以设置一个HTTP触发器,(别名1,函数1)也可以设置一个HTTP触发器。
  • 说明:Request Headers key 中包含以下字段会被忽略掉,因为 FC 默认会带以下字段,不支持用户自定义。同时以 x-fc- 开头的 key 也会被忽略掉。

    • accept-encoding
    • connection
    • keep-alive
    • proxy-authorization
    • te
    • trailer
    • transfer-encoding
  • 说明:Response Headers key 中包含以下字段会被忽略掉,因为 FC 默认会带以下字段,不支持用户自定义。同时以 x-fc- 开头的 key 也会被忽略掉。

    • connection
    • content-length
    • content-encoding
    • date
    • keep-alive
    • proxy-authenticate
    • server
    • trailer
    • transfer-encoding
    • upgrade
    • content-disposition: attachment (设置自定义域名后将不添加此字段)

Request 限制项

如果超过以下限制,会抛出 400 状态码和 InvalidArgument 错误码

  • headers 的大小:headers 中的所有 key 和 value 的大小不得超过 4 KB。
  • path 大小:包括各个 query params,path 的大小不得超过 4 KB。
  • body 大小:HTTP body 的大小不得超过 6 MB。

Response 限制项

如果超过以下限制,会抛出 502 状态码和 BadResponse 错误码。

  • headers 的大小:headers 中的所有 key 和 value 的大小不得超过 4 KB。
  • body 大小:HTTP body 的大小不得超过 6 MB。

HTTP 触发器的接口形式

HTTP 触发器的函数接口和函数计算原本的函数接口是有差异的,目前运行环境支持 Nodejs runtime , Python runtime 和 PHP runtime,后续支持Java runtime。

关于接口形式的详细信息,请参考

如图所示,是普通函数(左)与设置 HTTP 触发器的函数(右)的对比。如果您设置 HTTP 触发器后依然使用普通接口,请及时改正。

Nodejs:

nodejs_comparePython:

python_compare

配置 HTTP 触发器

组装 HTTP 触发器 URL

您可以通过发送 HTTP 请求到如下地址触发函数:

  1. // 普通的HTTP触发器URL
  2. <account_id>.<region>.fc.aliyuncs.com/<version>/proxy/<serviceName>/<functionName>/[action?queries]
  3. // 使用版本管理时的HTTP触发器URL
  4. <account_id>.<region>.fc.aliyuncs.com/<version>/proxy/<serviceName>.<qualifier>/<functionName>/[action?queries]
  • “version”为 函数计算 API 的版本,请参考 version
  • “serviceName”为触发器指向的服务,”qualifier” 为触发器指向的服务的版本或别名,链接符为“.“,请参考版本管理。服务在使用版本的情况下,URL不指定“qualifier”,请求会被LATEST版本处理。
  • “queries” 为 http 请求的查询参数。

例如:

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

HTTP 触发器 Config

HTTP 触发器 Config 格式如下所示:

  1. {
  2. "authType" : "anonymous",
  3. "methods" : ["GET", "POST"]
  4. }

HTTP 触发器 Config 主要有两个字段,包括:

  • authType:鉴权类型,取值范围:
    • anonymous:不需要身份验证,支持匿名访问,安全性低。
      示例:
      1. curl "<account-id>.<region>.fc.aliyuncs.com/2016-08-15/proxy/serviceName/functionName/action?hello=world"
    • function:需要身份验证,不支持匿名访问,安全性高。需要通过 签名认证,http request 的 header 中要传入 AuthorizationDate 信息,其中 Date 为 GMT 格式,且参与签名的运算,服务器端会以 Date 的时间计算签名,并与传入的 Authorization 的值进行比对,若签名比对成功且当前时间与 Date 时间相差 15 min 以内,才判定认证通过。
  • methods:HTTP 触发器支持的访问方法:
    • HEAD: HTTP HEAD 方法
    • GET : HTTP GET 方法
    • POST : HTTP POST 方法
    • PUT : HTTP PUT 方法
    • DELETE : HTTP DELETE 方法

示例 1. 控制台操作

本示例展示了使用控制台设置 HTTP 触发器的方式。

对触发器和创建触发器有困惑的同学可参考文章 触发器简介创建触发器

步骤 1. 设置 HTTP 触发器

可以在创建函数的时候设置触发器,也可以在函数创建完成后,选择触发器为函数设置触发器。

在创建函数时设置触发器

  1. 登录 函数计算管理控制台

  2. 选择地域,如华东 2(上海)。

  3. 在左侧导航栏选择服务。

  4. 单击 创建函数,在创建函数页面:

    1. 单击 选择全部的语言,在下拉菜单中选择 nodejs8。
    2. 选择 空白函数
    3. (可选)按如下图示配置 HTTP 触发器,单击 下一步。您也可以选择 不创建触发器
      创建触发器
    4. 创建函数并填写 所在服务函数名称描述信息运行环境 信息。
    5. 代码配置 部分,选择 在线编辑,并粘贴以下 Node.js runtime 的 HTTP 函数的示例代码。

      1. var getRawBody = require('raw-body')
      2. module.exports.handler = function (request, response, context) {
      3. // get requset header
      4. var reqHeader = request.headers
      5. var headerStr = ' '
      6. for (var key in reqHeader) {
      7. headerStr += key + ':' + reqHeader[key] + ' '
      8. };
      9. // get request info
      10. var url = request.url
      11. var path = request.path
      12. var queries = request.queries
      13. var queryStr = ''
      14. for (var param in queries) {
      15. queryStr += param + "=" + queries[param] + ' '
      16. };
      17. var method = request.method
      18. var clientIP = request.clientIP
      19. // get request body
      20. getRawBody(request, function (err, data) {
      21. var body = data
      22. // you can deal with your own logic here
      23. // set response
      24. // var respBody = new Buffer('requestURI' + requestURI + ' path' + path + ' method' + method + ' clientIP' + clientIP)
      25. var respBody = new Buffer('requestHeader:' + headerStr + '\n' + 'url: ' + url + '\n' + 'path: ' + path + '\n' + 'queries: ' + queryStr + '\n' + 'method: ' + method + '\n' + 'clientIP: ' + clientIP + '\n' + 'body: ' + body + '\n')
      26. // var respBody = new Buffer( )
      27. response.setStatusCode(200)
      28. response.setHeader('content-type', 'application/json')
      29. response.send(respBody)
      30. })
      31. };
    6. 单击 下一步
    7. (可选)配置权限。
    8. 会对信息无误后,单击 创建

在函数创建完成后设置触发器

  1. 登录 函数计算管理控制台

  2. 选择地域,如华东 2(上海)。

  3. 在左侧导航栏选择服务。

  4. 在服务中选中函数。

  5. 单击 触发器 > 创建触发器

  6. 在创建触发器页面,按如下图示配置 HTTP 触发器,单击 确定

    create-trigger

步骤 2. 调试触发器

  1. 在目标函数页面,单击 代码执行,向下滚动页面。

  2. 单击 Params,填入键值对,您的键值对会自动添加到 HTTP URL 上。

    console-demo

  3. 单击 Header 设置请求 Header,填入您的键值对。当需要认证访问时,管理控制台调试页面的请求 Header 会自动包含 Date 和 Authorization 的键。

  4. 单击 执行

示例 2. 使用 Fun 创建 HTTP Trigger(推荐)

Fun 提供了 HTTP 触发器 的支持,可以实现函数触发器的创建与更新。下面,我们介绍使用 Fun 配置 HTTP 触发器的步骤。

首先在项目根目录下创建一个 index.js 文件。

  1. var getRawBody = require('raw-body')
  2. module.exports.handler = function (request, response, context) {
  3. // get request body
  4. getRawBody(request, function (err, body) {
  5. var respBody = {
  6. headers: request.headers,
  7. url: request.url,
  8. path: request.path,
  9. queries: request.queries,
  10. method: request.method,
  11. clientIP: request.clientIP,
  12. body: body.toString()
  13. };
  14. response.setStatusCode(200);
  15. response.setHeader('content-type', 'application/json');
  16. response.send(JSON.stringify(respBody, null, 4));
  17. });
  18. };

接下配置相关服务。在项目根目录创建一个 template.yml 文件:

  1. ROSTemplateFormatVersion: '2015-09-01'
  2. Transform: 'Aliyun::Serverless-2018-04-03'
  3. Resources:
  4. FunDemo:
  5. Type: 'Aliyun::Serverless::Service'
  6. httpdemo:
  7. Type: 'Aliyun::Serverless::Function'
  8. Properties:
  9. Handler: index.handler
  10. CodeUri: ./
  11. Description: 'http trigger demo!'
  12. Runtime: nodejs8
  13. Events:
  14. http-test:
  15. Type: HTTP
  16. Properties:
  17. AuthType: ANONYMOUS
  18. Methods: ['GET', 'POST', 'PUT']

代码以及模板文件编写完成后,就可以使用 fun deploy 命令一键将服务部署到线上环境了:

  1. $ fun deploy
  2. using region: cn-hangzhou
  3. using accountId: ***********3557
  4. using accessKeyId: ***********r3Ra
  5. using timeout: 300
  6. Waiting for service FunDemo to be deployed...
  7. Waiting for function httpdemo to be deployed...
  8. Waiting for packaging function httpdemo code...
  9. package function httpdemo code done
  10. Waiting for HTTP trigger http-test to be deployed...
  11. methods: [ 'GET', 'POST', 'PUT' ]
  12. url: https://1911504709953557.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/FunDemo/httpdemo/
  13. function httpdemo deploy success
  14. function FunDemo deploy success
  15. service FunDemo deploy success

打开浏览器访问 https://1911504709953557.cn-hangzhou.fc.aliyuncs.com/2016-08-15/proxy/FunDemo/httpdemo/ 即可触发函数的执行。对于 HTTP 触发器,服务端会为 response header 中强制添加 content-disposition: attachment 字段,此字段会使得返回结果在浏览器中以附件的方式打开。此字段无法覆盖,使用自定义域名将不受影响。更多信息请参见 函数计算常见问题

如果修改了 HTTP Trigger 的配置,重新执行 fun deploy 即可。

如果想在本地单步调试、运行 http trigger 的函数,可以参考 开发函数计算的正确姿势 —— Http Trigger 本地运行调试

更多的配置规则 请参考

Fun 的更多教程 请参考

示例 3. SDK 编程

Python SDK 为例,示范如何使用 SDK 创建 HTTP 触发器。

注意:使用 HTTP 触发器的接口的函数只能通过向 指定地址 发送 HTTP 请求的方式调用,不能通过 SDK 中的 invoke_function 方法调用。

前提条件

  • 您已经部署了 Python 环境。
  • 您已经安装了函数计算 Python SDK 工具,您可以本地运行 pip install aliyun-fc2 获取函数计算 Python SDK。

操作步骤

  1. 编写函数计算 Function,并将 示例代码 粘贴到 code 文件夹下的 main.js 文件中。

  2. 创建文件 create_http_trigger.py 并粘贴如下 Python 代码。

  1. import fc2
  2. import os
  3. def main():
  4. service_name = "http_trigger_service"
  5. func_name = "test_http_trigger_node"
  6. endpoint = os.getenv("FC_ENDPOINT")
  7. url = "%s/2016-08-15/proxy/%s/%s" % (endpoint, service_name, func_name)
  8. print url
  9. fc_client = fc2.Client(
  10. endpoint=endpoint,
  11. accessKeyID=os.getenv("ACCESS_KEY_ID"),
  12. accessKeySecret=os.getenv("ACCESS_KEY_SECRET"),
  13. Timeout=5)
  14. fc_client.create_service(service_name)
  15. fc_client.create_function(service_name, func_name, "nodejs6", "main.handler", codeDir='./code')
  16. trigger_config = {
  17. "authType" : "anonymous",
  18. "methods" : ["GET", "POST"],
  19. }
  20. fc_client.create_trigger(service_name, func_name, "trigger_on_echo", "http", trigger_config, "dummy_arn", "")
  21. main()
  1. 运行 python create_http_trigger.py 创建 HTTP 触发器。

  2. 通过向函数发送 HTTP 请求的方式触发函数

    例如:

    1. curl -v "<account-id>.<region>.fc.aliyuncs.com/2016-08-15/proxy/http_trigger_service/test_http_trigger_node/action"

执行结果如下

结果

示例 3. initializer 接口

当您在使用 HTTP 触发器时同样可以做到将初始化逻辑放到 initializer 函数中,当 initializer 和 HTTP 触发器结合使用时,各自保持原有的结构即可,不需做特殊改动。关于 initializer 的详细介绍可以参考 initializer 入口定义

以 Python runtime 为例的示例代码如下:

  1. # -*- coding: utf-8 -*-
  2. import logging
  3. HELLO_WORLD = b"Hello world!\n"
  4. def initializer(context):
  5. logger = logging.getLogger()
  6. logger.info("initialized")
  7. def handler(environ, start_response):
  8. logger = logging.getLogger()
  9. logger.info("run after initialized")
  10. context = environ['fc.context']
  11. request_uri = environ['fc.request_uri']
  12. for k, v in environ.items():
  13. if k.startswith("HTTP_"):
  14. # process custom request headers
  15. pass
  16. # do something here
  17. status = '200 OK'
  18. response_headers = [('Content-type', 'text/plain')]
  19. start_response(status, response_headers)
  20. return [HELLO_WORLD]

示例 4. 使用 fcli 创建 HTTP trigger

以 nodejs6 为 runtime 为例,使用命令行工具 fcli 为函数创建HTTP trigger:

  • 我们创建 http_echohttp_echo/code 目录
  • 将代码放在 http_echo/code/index.js 中,并创建 config.json
  1. {
  2. "triggerConfig": {
  3. "authType" : "anonymous",
  4. "methods" : ["GET", "POST"]
  5. }
  6. }
  • 使用下面的命令在服务 test_service 中新建函数 test_echo
  1. fcli function create -s test_service -f test_echo --runtime nodejs6 --code-dir code --handler index.handler
  • 使用下面的命令获取函数 test_echo 的所有 trigger 信息:
  1. fcli trigger list -s test_service -f test_echo
  • 使用下面的命令在服务 test_service 中的 test_echo 函数上创建名为 test_trigger_nameHTTP 类型 trigger
  1. fcli trigger create -s test_service -f test_echo --trigger-name test_trigger_name --type http --source-arn dummy --config config.json
  • 使用下面的命令为 test_echo 更新 trigger test_trigger_name 的信息:
  1. fcli trigger update -s test_service -f test_echo -t test_trigger_name --trigger-config config.json
  • 使用下面的命令删除 test_echo 上的 trigger test_trigger_name
  1. fcli trigger delete -s test_service -f test_echo -t test_trigger_name
  • 具体详见 视频(支持命令拷贝):

问题诊断

错误主要分为请求错误和函数错误两种。请求错误是用户发送的 request 请求不符合标准,在返回的 response 里报错状态码为 4xx。函数错误即编写的函数有问题,会报 5xx状态码 ,下面对请求错误和函数错误的可能出现场景进行描述,以便您迅速排查问题。

错误类型 X-Fc-Error-Type HTTP 状态码 原因分析 是否依然计费
请求错误 FcCommonError 400 用户的请求超过 response 限制项 的限制
FcCommonError 400 调用需要身份认证函数的 request 没有传 Date 信息或 Authorization 信息
FcCommonError 403 调用需要身份认证函数的 request 的签名错误,即 Authorization 不正确,由于 Date 参与签名计算,且超过 15 min,签名失效,一种常见的原因是使用需要访问认证的 http 触发器,request header 中发送的 Date 据当前时间超过 15 min,导致签名失效
FcCommonError 403 用户的 request 请求使用了 http trigger 中未配置的 method ,比如 http trigger 中的 methods 只配置了 GET 方法,却发送 POST 方法的 http 请求
FcCommonError 404 向没有设置 http trigger 的函数发送 http 请求
用户流控 FcCommonError 429 用户被流控,可减小并发量或者联系函数计算开发团队提高并发度
函数错误 UnhandledInvocationError 502 函数的返回值超过 response 限制项 的限制
UnhandledInvocationError 502 函数代码有语法错误或者异常
UnhandledInvocationError 502 向未使用 http 接口 的函数发送 http 请求
系统错误 FcCommonError 500 函数计算系统错误,可重试解决
系统流控 FcCommonError 503 函数计算系统流控。指数退避重试。

如果问题还未能解决,请 联系我们