社区/学习指南/小程序·云开发高级教程

云接入与HTTP触发

云接入是云开发基于云函数之上为开发者提供的 HTTP 访问服务,开发者可以轻松使用 POST、PUT、GET、DELETE 等方法通过 HTTP 请求访问到云开发环境内的全部资源,而不需要使用 Web 端 SDK。而且云接入天然支持跨域请求,将域名添加至 Web 安全域名中,这个域名里的网页便可以跨域访问云接入。当使用云函数时,系统会自动预配 TLS 证书,因此我们可以通过安全连接调用云函数。

14.5.1 使用云接入访问云函数

给云函数启用云接入的方式非常简单,我们可以使用腾讯云云开发网页控制台以及 Cloudbase Cli 命令两种方式。

1、云开发控制台启动云接入

打开腾讯云云开发网页控制台的云函数菜单,然后点击HTTP 触发标签,开启 HTTP 触发,云接入就启动啦,云接入的默认域名就是https://{你的环境id}.service.tcloudbase.com/

在前面我们已经上传了一个 webtest 的云函数(其他云函数也都可以的哦),点击进入 webtest 云函数的管理页,然后点击右上角的编辑,在 HTTP 触发路径里输入/webtest(也可以是其他值),保存之后,在浏览器里打开以下链接(网页控制台直接就有链接)就可以访问云接入了:


https://{你的环境id}.service.tcloudbase.com/webtest

大家可以对比一下 event、context 对象与调用云函数返回的对象有什么不同。使用云接入调用云函数时,HTTP 请求会被转化为特殊的结构体,称之为集成请求,结构如下:


{

    path: 'HTTP请求路径,如 /hello',

    httpMethod: 'HTTP请求方法,如 GET',

    headers: {HTTP请求头},

    queryStringParameters: {HTTP请求的Query,键值对形式},

    requestContext: {云开发相关信息},

    body: 'HTTP请求体',

    isBase64Encoded: 'true or false,表示body是否为Base64编码'

}

这里的queryStringParameters是 HTTP 请求的 Query,我们可以在链接里传入一些参数,比如在访问云接入的链接里加一些参数:


https://xly-xrlur.service.tcloudbase.com/webtest?name=bbsky&location=shenzhen

2、使用 Cloudbase Cli 启动云接入

在前面我们已经了解到通过在终端输入cloudbase --help可以了解到 Cloudbase Cli 有哪些命令(尽管 cloudbase 是全局的,建议大家在云开发项目的根目录执行),我们可以看到关于云接入的命令有:


  service:switch [options]                  开启/关闭 HTTP Service 服务

  service:auth:switch [options]             开启/关闭 HTTP Service 服务访问鉴权

  service:create [options]                  创建 HTTP Service

  service:delete [options]                  删除 HTTP Service

  service:list [options]                    获取 HTTP Service 列表

  service:domain:bind [options] <domain>    绑定自定义 HTTP Service 域名

  service:domain:unbind [options] <domain>  解绑自定义 HTTP Service 域名

  service:domain:list [options]             查询自定义 HTTP Service 域名

由这些命令,我们可以在终端里输入以下命令来开启和关闭云接入,比如开启云开发环境 id 为xly-xrlur的云接入服务:


cloudbase service:switch -e xly-xrlur

而我们可以执行以下命令创建一条云接入路由,路径为 /webtest,指向的云函数为 webtest:


cloudbase service:create -p /webtest -f webtest

除了可以使用浏览器里打开云接入的链接,我们还可以使用 cURL 命令行来调用云接入,比如我们可以在终端输入以下命令:


curl https://xly-xrlur.service.tcloudbase.com/webtest

3、参数的传入与获取总结

我们有必要重新梳理一下一些参数的传入与获取相关的知识,我们往云函数里传入参数的方式有调用云函数时传入参数、访问云接入链接时传入参数以及配置云函数环境时添加配置信息,那这三种方法又是如何获取这些参数呢?(还有一种是通过 require 模块、文件,这里就不多做介绍了)

调用云函数传入参数

在小程序端、Web 端以及云函数端,我们可以通过 callFunction 的接口(小程序端为 wx.callFunction、云函数端为 cloud.callFunction、web 端为 app.callFunction)来调用云函数,并传入参数:

wx.cloud.callFunction({
  name: "webtest", //被调用的云函数的名称

  data: {
    userInfo: {
      name: "李东bbsky",
    },

    id: "20200420001",
  },
});

那我们应该如何获取使用调用云函数时传递的参数呢?我们可以从 event 对象里拷贝:

const { userInfo, id } = event;

访问云接入链接时传入参数

我们通过访问云接入链接或 axios 等进行 HTTP 请求的方式也能向云函数里传递参数,这个参数会在 queryStringParameters 对象里,我们可以通过

const { name, title } = event.queryStringParameters;

云函数配置信息传入参数

我们可以在云开发控制台对云函数进行一些参数的配置,也就是新增环境变量的字段,这个参数在云函数的获取方式如下:

const { school, name } = process.env;

14.5.2 后台函数与云接入

有了云接入的概念,我们可以把云函数分为两类,在前面的章节云函数主要用于调用云函数、处理数据库、云存储云调用,我们可以称之为后台函数,而 HTTP 函数则是我们可以通过标准 HTTP 请求来调用的。

参考上节 Web 端云开发的内容,在 functions 文件夹里新建一个云函数比如 backfunction,然后在 index.js 里输入以下代码,注意有一个 dbName 的参数会由 HTTP 请求传入:

const tcb = require("@cloudbase/node-sdk");

tcb.init({
  env: "xly-xrlur",
});

const db = tcb.database();

const _ = db.command;

exports.main = (event, context) => {
  const { dbName } = event.queryStringParameters; //注意queryStringParameters的来源

  return db
    .collection(dbName)

    .where({
      gdp: _.gt(3000),
    })

    .get();
};

然后安装该云函数的依赖,将云函数的代码部署上传到云端,并开启云接入以及设置路由,具体操作前面都有介绍,然后我们在浏览器里打开如下链接,就能看到云函数返回的数据了。


http://xly-xrlur.service.tcloudbase.com/backfunction?dbName=china

在小程序端我们知道获取获取可以使用wx.request()接口,而在 web 端我们则可以使用 axios,在静态托管的 html 页面,比如打开之前 public 文件夹里的 index.html,输入以下代码,然后打开链接,然后在浏览器的控制台可以获取到的数据啦:

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

<script>
  const url =
    "https://xly-xrlur.service.tcloudbase.com/backfunction?dbName=china";

  axios
    .get(url)
    .then((res) => {
      console.log(res);

      console.log(res.data);
    })
    .catch((err) => {
      console.log(err);
    });
</script>

14.5.3 返回集成响应

云函数可以返回 String、Object、Number 等类型的数据,还能返回集成响应,云接入会将返回值转化成正常的 HTTP 响应,我们接下来使用云接入来返回一些静态资源文件。

1、使用集成响应返回 HTML

使用 VS Code 在 functions 文件夹里新建一个云函数,比如 sendhtml,以及 assets 文件夹,里面存放我们要返回的 HTML 文件,结构如下:


├── sendhtml   //sendhtml云函数目录

│   └── assets

│       └── index.html

│   └── index.js

│   └── config.json

│   └── package.json

然后在 index.js 里输入以下代码,读取云函数目录 assets 文件夹里 index.html,并返回 HTML,这个云函数就和以往的云函数有很大的不同啦:

const tcb = require("@cloudbase/node-sdk");

tcb.init({
  env: "xly-xrlur",
});

const fs = require("fs");

const path = require("path");

exports.main = async (event, context) => {
  //path.resolve() 方法将路径或路径片段的序列解析为绝对路径

  const html = fs.readFileSync(path.resolve(__dirname, "./assets/index.html"), {
    encoding: "utf-8",
  });

  return {
    statusCode: 200,

    headers: {
      "content-type": "text/html",
    },

    body: html,
  };
};

在 assets 文件夹里 index.html 可以输入一些 html 代码,然后将 sendhtml 云函数部署上传并开启云接入,以及设置路由如/sendhtml之后,用浏览器打开云接入的地址,返回的 HTML 就被浏览器自动解析了。

2、使用集成响应返回其他类型的文件

除了 html 文件,还能返回其他类型的文件,在响应中,Content-Type 实体头部用于指示资源的 MIME 媒体类型,告诉 Web 端返回的内容类型。媒体类型有很多,比如:

类型 描述 典型示例
text 普通文本类型 text/plain, text/html, text/css, text/javascript
image 图像类型 image/gif, image/png, image/jpeg, image/bmp, image/webp, image/x-icon, image/vnd.microsoft.icon
audio 音频文件 audio/midi, audio/mpeg, audio/webm, audio/ogg, audio/wav
video 视频文件 video/webm, video/ogg
application 二进制数据
<p><code>application/octet-stream</code>, <code>application/pkcs12</code>, <code>application/vnd.mspowerpoint</code>, <code>application/xhtml+xml</code>, <code>application/xml</code>,&nbsp; <code>application/pdf</code></p>

将 content-type 分别设置为 application/javascript、text/css,即可在 body 中返回 JavaScript 文件和 css 文件,html、js、css 文件是静态网站的核心文件,都是可以返回的,这样就用集成响应返回一个完整的静态网站啦。注意用集成请求返回的静态网站和静态托管之间的区别哦

将 content-type 设置为 image/png 以及将 isBase64Encoded 设置为 true,就能返回图片的二进制文件,这个也可以和云存储结合起来使用。比如我们可以写如下云函数,先下载云存储里面的图片,将 Buffer 转成 base64 格式的图片,然后返回,这样我们就能通过云接入的链接查看到图片了:

const cloud = require("wx-server-sdk");

cloud.init({
  env: "xly-xrlur",
});

exports.main = async (event, context) => {
  const fileID =
    "cloud://xly-xrlur.786c-xly-xrlur-1300446086/1572315793634-953.png";

  const res = await cloud.downloadFile({
    fileID: fileID,
  });

  const buffer = res.fileContent;

  const base64img = await buffer.toString("base64");

  return {
    isBase64Encoded: true,

    statusCode: 200,

    headers: {
      "content-type": "image/png",
    },

    body: base64img,
  };
};

本文出自 李东bbsky