社区/学习指南/微信云开发高级教程

HTTP处理

在小程序端我们可以使用 wx.request 来与第三方 api 服务进行数据交互,那云函数除了可以直接给小程序端提供数据以外,能不能从第三方服务器获取数据呢?答案是肯定的,而且在云函数中使用 HTTP 请求访问第三方服务可以不受域名限制,即不需要像小程序端一样,要将域名添加到 request 合法域名里;也不受 http 和 https 的限制,没有域名只有 IP 都是可以的,所以云函数可以应用的场景非常多,即能方便的调用第三方服务,也能够充当一个功能复杂的完整应用的后端。不过需要注意的是,云函数是部署在云端,有些局域网等终端通信的业务只能在小程序里进行。

node 流行的 HTTP 库比较多,比如 got、superagent、request、axios、request-promise、fech 等等,推荐大家使用 axios,axios 是一个基于 promise 的 HTTP 库,可以使用在浏览器和 Nodejs 环境中,下面也会以 axios 为例。

11.10.1 get 请求

使用开发者工具,创建一个云函数,如 axios,然后在 package.json 增加 axios 最新版 latest 的依赖并用 npm install 安装:


"dependencies": {

  "wx-server-sdk":"latest",

  "axios": "latest"

}

然后在 index.js 里输入以下代码,在前面章节里,我们在小程序端调用过知乎日报的 API,下面还以知乎日报的 API 为例:

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

cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV,
});

const axios = require("axios");

exports.main = async (event, context) => {
  const url = "https://news-at.zhihu.com/api/4/news/latest";

  try {
    const res = await axios.get(url);

    //const util = require('util')

    //console.log(util.inspect(res,{depth:null}))

    return res.data;
  } catch (e) {
    console.error(e);
  }
};

在小程序端调用这个云函数,就能返回从知乎日报里获取到的最新文章和热门文章,云函数端获取知乎日报的数据就不需要添加域名校验,比小程序端的 wx.request 方便省事很多。

注意,在上面的案例中,我们返回的不是整个 res(response 对象),而是 response 对象里的 data。直接返回整个 res 对象,会报Converting circular structure to JSON的错误,如果你想返回整个 res,可以取消上面代码里面的注释。Node 的util.inspect(object,[showHidden],[depth],[colors])是一个将任意对象转换为字符串的方法,通常用于调试和错误输出。

上面的知乎链接本来就是 API,返回的是 json 格式的数据,所以可以直接使用 axios.get(),axios 还可以用于爬虫,爬取网页,比如下面的代码就是爬取百度首页,并返回首页里的<title></title>里的内容(也就是网页的标题):

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

cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV,
});

const axios = require("axios");

exports.main = async (event, context) => {
  try {
    const res = await axios.get("https://baidu.com");

    const htmlString = res.data;

    return htmlString.match(/<title[^>]*>([^<]+)<\/title>/)[1];
  } catch (e) {
    console.error(e);
  }
};

如果想使用云函数做爬虫后台,抓取网页数据,可以使用 cheerio 和 puppeteer 等第三方开源依赖,这里就不多做介绍了。

11.10.2 post 请求

结合前面在网络 API 里讲过的聚合数据历史上的今天 API,我们也可以在云函数端发起 post 请求:

const now = new Date(); //在云函数字符串时间时,注意要修改云函数的时区,方法在云函数实用工具库里有详细介绍

const month = now.getMonth() + 1; //月份需要+1

const day = now.getDate();

const key = ""; //你的聚合KEY

const url = "http://api.juheapi.com/japi/toh";

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

cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV,
});

const axios = require("axios");

exports.main = async (event, context) => {
  try {
    const res = await axios.post(url, {
      key: key,

      v: 1.0,

      month: month,

      day: day,
    });

    // const res = await axios.post(`url?key=${key}&v=1.0&month=${month}&day=${day}`)

    return res;
  } catch (e) {
    console.error(e);
  }
};

11.10.3 使用 axios 下载文件

要使用 axios 下载文件,需要将 axios 的 responseType 由默认的 json 修改为 stream,然后将下载好的文件上传到云存储里,也可以将下载好的文件写入到云函数临时的 tmp 文件夹里,用于更加复杂的操作。

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

cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV,
});

const axios = require("axios");

//const fs = require('fs');

exports.main = async (event, context) => {
  try {
    const url =
      "https://tcb-1251009918.cos.ap-guangzhou.myqcloud.com/weapp.jpg";

    const res = await axios.get(url, {
      responseType: "stream",
    });

    const buffer = res.data;

    //我们也还可以将下载好的图片保存在云函数的临时文件夹里

    // const fileStream = await fs.createReadStream('/tmp/axiosimg.jpg')

    return await cloud.uploadFile({
      cloudPath: "axiosimg.jpg",

      fileContent: buffer,
    });
  } catch (e) {
    console.error(e);
  }
};

本文出自 李东bbsky