0.4.4 • Published 2 years ago

scf-service-stack v0.4.4

Weekly downloads
43
License
ISC
Repository
-
Last release
2 years ago

SCF Service Stack

本模块是一个工具集,在开发腾讯小程序的云函数时,为了实现一个 serverless 的 http/https 服务,旧的 tcb-router 无法对实际的 path 做有效的判断,无法统一做异常处理,在对 path 进行判断时也不够精确,例如'/user/:name'这种类型的路径无法识别,所以自己新开发了一个 router,让会用 express 开发的开发者们快速上手。

本模块目前有两功能:

  • 云函数在开发时模拟 express 的开发,让开发者平滑过渡,也方便移植。
  • 本地开发时,启动一个本地服务,模拟腾讯云转换请求的过程,调用所开发的云函数,增加开发效率,方便 debug

准备: 有一个微信小程序的云函数,并且该云函数已部署到云端开通了云接入(HTTP 访问),官方文档


Router 功能:

// webservice/index.js
const {
  bodyParser,
  staticHandler,
  cookieParser,
  LocalStorageClient,
  TCBStorageClient,
  sessionParser
} = require('scf-service-stack').middlewares;
const SCFRouter = require('scf-service-stack').router;
const wechatRouter = require('./routers/wechat.router');
// 这是一个云函数的的入口
exports.main = async (request, context) => {
  // 此时的request,结构参照[腾讯文档](https://docs.cloudbase.net/service/access-cloud-function.html#yun-han-shu-de-ru-can)
  const app = new SCFRouter(request, {
    templateFolder: path.join(__dirname, 'templates') // 存放ejs文件的目录
  });
  // 中间件的导入
  app.use(staticHandler(path.join(__dirname, 'public'))); // 静态文件地址
  app.use(bodyParser);
  app.use(cookieParser);
  app.use(sessionParser(new LocalStorageClient(), { maxAge: 600 })); // session存入本地,但是因为云函数为动态资源,所以不推荐使用,有很大概率取不到值
  // app.use(   // 用云数据库来存放session可以保证session跨资源也不丢失
  //   sessionParser(
  //     new TCBStorageClient(
  //       process.env['REMOTE_CACHE_SECRET_ID'],   // session对应云环境的secret ID
  //       process.env['REMOTE_CACHE_SECRET_KEY'],  // session对应云环境的secret Key
  //       process.env['REMOTE_CACHE_ENVID'],       // session对应云环境的ENV ID
  //       process.env['REMOTE_CACHE_COLLECTION']   // 将session存入该环境中的某个collection名称
  //     ),
  //     {maxAge: 600}
  //   )
  // );

  // 同express一样,use代表不过滤 httpMethod
  app.use(async (req, res, next) => {
    // 这里可以写一些中间件的逻辑,鉴权等等
    next();
  });

  app.get('/', async (req, res) => {
    res.render('index'); // 请求页面
  });

  app.post('/test/:user', async (req, res) => {
    res.json(req.params); // 请求返回json数据,req.params为url中path的参数
  });

  app.extends(wechatRouter); // 继承另一个router

  // 此段逻辑可以写在最后,用来处理未定义的path
  app.use(async (req, res, next) => {
    throw new Error('no mapping routers'); // 有任何报错都会返回500的请求码
  });

  return app.serve();
};
// webservice/routers/wechatRouter.js
const route = async (sr) => {
  // 设置一个cookie
  sr.use('/test', async (req, res) => {
    console.log(req.cookies);
    res.cookie('sid', 'asdasdsadasdas');
    res.json(req.cookies);
  });

  sr.use('/text', async (req, res) => {
    res.text('123');
  });

  sr.use('/test/session', async (req, res) => {
    // session 模块在本地可以用local
    console.log(req.cookies['sid']);
    req.session.a = 1;
    req.session.b = 1;
    res.text('123');
  });

  sr.use('/test/session2', async (req, res) => {
    console.log(req.cookies['sid']);
    req.session.a++;
    res.json(req.session);
  });

  sr.use('/test/delete-session', async (req, res) => {
    delete req.session.a;
    res.json(req.session);
  });

  sr.get('/test-regex/:a/:b', async (req, res, next) => {
    console.log(req.params);
    next();
  });

  sr.get('/test-regex/:c/:d', async (req, res, next) => {
    console.log(req.params);
    next();
  });
};

module.exports = route;

Router 功能备注:

  1. app.use(func)这个方法可以多次使用,只要前面的 handler 都调用了 next()方法,则所有符合规则的都会顺次执行
  2. (已优化)集成响应相关内容参照文档,若有需要,请在 issue 里写明需求。后续上线 responseGenerator 功能可以更简便的返回复杂类型,比如用 ejs 模版引擎等。
  3. 目前大部分使用场景都在以上代码里有范例

Simulator 功能

假设有一个云函数叫做 webservice,代码内容如 Router 里的 demo 类似。为了尽可能便捷的开发测试,可以启动一本地模拟服务去转换请求。 目录结构为:

root
 - public
   - ...    // 静态资源
 - routes
   - *.js   // 所有的子路由
 - app.js   // 逻辑入口
 - env.json // 环境变量配置
 - index.js // 主入口
 - package.json
// index.js
const fs = require('fs');
const Simulator = require('scf-service-stack').simulator;
const simulator = new Simulator(require('./env.json'));
simulator.deploy(require('./app'), {
  key: fs.readFileSync(`cert.key`),
  cert: fs.readFileSync(`cert.pem`)
});
// deploy方法第二个参数在本地启动时如果是http请求可为空
// app.js
// 同第一部分webservice/index.js,也就是云函数的入口文件

这里有一个配置文件的 env.json:

{
  "functionEnvVariables": {
    "ENV1": "1",  // 环境变量都写在这里,只能是字符串
    "ENV2": "2"
  },
  "context": {
    "appId": "wxtinkcaiappid831",
    "uin": "mockuintinkcai831",
    "envId": "local"
  },
  "port": 3000, // 启动的本地端口
  "protocol": "http" // 是否开启https,或者为http
}

后续:

目前已经有一个功能很全的 CI/CD 流程,可实现一个云函数做成一个综合性的网站,利用云开发提供的存储和数据库功能提供完整服务,在一定流量内免费使用。如有需要请联系Tink.Cai@dbschenker.com或者在该资源下留言。

0.4.4

2 years ago

0.4.3

2 years ago

0.4.2

3 years ago

0.4.1

3 years ago

0.4.0

3 years ago

0.3.19

3 years ago

0.3.18

3 years ago

0.3.17

3 years ago

0.3.16

3 years ago

0.3.15

3 years ago

0.3.14

3 years ago

0.3.13

3 years ago

0.3.12

3 years ago

0.3.11

3 years ago

0.3.10

4 years ago

0.3.9

4 years ago

0.3.8

4 years ago

0.3.7

4 years ago

0.3.6

4 years ago

0.3.5

4 years ago

0.2.2

4 years ago

0.3.4

4 years ago

0.3.3

4 years ago

0.3.2

4 years ago

0.3.1

4 years ago

0.3.0

4 years ago

0.2.1

4 years ago

0.2.0

4 years ago

0.1.0

4 years ago

0.0.7

4 years ago

0.0.6

4 years ago

0.0.5

4 years ago

0.0.4

4 years ago

0.0.3

4 years ago

0.0.2

4 years ago

0.0.1

4 years ago