koa 中间件

本文涉及的产品
Serverless 应用引擎 SAE,800核*时 1600GiB*时
云原生网关 MSE Higress,422元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 在写一个服务端应用的时候,一般都会使用到作为静态服务器,node 搭建静态服务请查看我以前文章,express中间件实现静态资源服务的话可以使用 express.static()来实现,那么koa如何实现呢? 其实对于一个静态服务的话,只要你会node这个底层的原理,express 或者 koa 这些上层应用都是基于底层原理来的

koa 是一个轻量级(对比express 区别请查看我上一篇文章)web 服务的框架,里面没有自带的中间件,因此我们需要来自己实现中间件或者使用第三方人家开发好的中间件。


在写一个服务端应用的时候,一般都会使用到作为静态服务器,node 搭建静态服务请查看我以前文章,express中间件实现静态资源服务的话可以使用 express.static()来实现,那么koa如何实现呢? 其实对于一个静态服务的话,只要你会node这个底层的原理,express 或者 koa 这些上层应用都是基于底层原理来的


步骤


1.获取路径的path,作为服务的话,需要提供一个根路径和静态资源的目录;

2.判断提供的path 是文件夹、文件或者不存在;

3.去读指定文件的内容,设置响应头;

4.给浏览器返回一个文件内容


代码如下:


const path = require('path');
const fs = require('fs')
// 这里使用mime 这个库来判断文件的类型,从而设置响应头
const mime = require('mime');
/**
 * 获取文件名称
 * @param {*} filename 
 * @param {*} root 
 * @returns 
 */
async function getFileName(filename, root) {
  // 获取文件的全路径,node 中规定,如果是以 \ 开头,就是绝对路径是一个跟路径
  const fullName = path.resolve(root, filename.substring(1));
  // 判断当前路径是文件还是文件夹或者不存在
  try {
    const fsStat = await fs.promises.stat(fullName);
    if (fsStat.isDirectory()) {
      // 如果是目录的话,那就需要补上默认文件
      const adtFileName = path.join('/index.html');
      return await getFileName(adtFileName, root);
    } else {
      return fullName;
    }
  } catch (error) {
    return null;
  }
}
/**
 * 读取静态资源目录
 * @param {*} root 
 * @returns 
 */
module.exports = function (root) {
  return async (ctx, next) => {
    if (ctx.method !== 'GET') {
      await next();
      return;
    }
    const filename = await getFileName(ctx.path, root)
    if (!filename) {
      // 文件不存在
      await next();
      return;
    }
    // 根据文件的后缀名响应文件
    const mimeType = mime.getType(filename);
    // 返回一个文件流
    ctx.body = fs.createReadStream(filename);
    // 设置文件的类型
    ctx.type = mimeType;
    await next();
  }
}
复制代码


手动实现 connect-history-api-fallback 中间件


单页应用中,我们会使用路由的history模式,刷新浏览器的时候,需要重新回到index.html页面,这个中间件在koa 中怎么实现呢?connect-history-api-fallback官网告诉我们有几个匹配规则,如下:


规则


39ac45f7b6ae2c1f251f5a637aedd856.png


``


1.只能匹配get请求


2.请求的header 的文件类型是text/html


3.请求不是一个重定向的请求,请求的path中不能包含·,因为带点的就意味着是请求的是一个静态资源,如,js,css,图片等


代码


module.exports = async function (ctx, next) {
  // 判断当前请求是不是get请求,请求的路径中是否包含.,并且请求头的类型是html文件
  if (ctx.method === "GET" &&
    ctx.headers.accept.includes("text/html") &&
    !ctx.path.includes(".")) {
    ctx.path = '/index.html'
  }
  await next();
}
复制代码


这个地方有一个小插曲,那就是,在使用静态资源的时候,需要使用绝对路径,不能使用相对路径,不然静态资源会不对,你可以打开单页应用打的包的路径绝对是以/开头的(前提是history模式的路由,hash路由也不会使用这个插件)。


550b5443819f1f7de537d61d0638834b.png


常用KOA中间件


Koa中间件 功能
@koa/router 官方中间件。借鉴了koa-router
用于处理路由的中间件,用法类似 express.Router
koa-bodyparser 解析请求体的中间件,支持
x-www-form-urlencoded, application/json格式的请求体
koa-views 渲染模板引擎的中间件,一般用于传统的服务端渲染
koa-static 用于搭建静态资源服务器的中间件
koa-static-cache 实现了http缓存的静态资源中间件
koa-session session中间件
koa-jwt 支持jwt的中间件
koa-compress 支持gzip动态压缩的中间件
koa-logger 日志记录中间件
@koa/cors 官方中间件。支持CORS跨域的中间件
@koa/multer 官方中间件,借鉴了koa-multer
用户处理文件上传的中间件
koa-connect 将express或connect中间件转换为koa中间件
http-proxy-middleware 代理中间件(这个中间件需要使用koa-cennect后才可以使用)
connect-history-api-fallback 单页应用支持
(这个中间件需要使用koa-cennect后才可以使用)
koa-convert 用于将旧版本的koa中间件转换为koa2中间件
相关文章
|
11月前
|
前端开发 JavaScript 中间件
78 # koa 中间件的实现
78 # koa 中间件的实现
42 0
|
11月前
|
前端开发 中间件
77 # koa 中间件的应用
77 # koa 中间件的应用
33 0
|
4月前
|
资源调度 JavaScript 前端开发
koa常用中间件
koa常用中间件
45 0
|
中间件
Koa 中间件
Koa 中间件
132 2
Koa 中间件
|
JavaScript 前端开发 中间件
尝试理解 Koa、Redux middleware 的演进过程
最近开发 web 端,用的是 Egg node.js 框架,期间实现的一些功能例如:权限检测、操作日志上报等都是基于框架的 middleware 机制件完成的。虽然最后完成了功能,但其实对中间件真正的实现机制、运行时序还不能做到完全的理解。 Egg 是基于 Koa 实现的,Koa 的代码量非常少,加起来也就 1000 多行,涉及到中间件核心的部分,也就不到 100 行,如果有耐心可以直接读
85 0
|
JavaScript 前端开发 中间件
尝试理解 Koa、Redux middleware 的演进过程
最近开发 web 端,用的是 Egg node.js 框架,期间实现的一些功能例如:权限检测、操作日志上报等都是基于框架的 middleware 机制件完成的。虽然最后完成了功能,但其实对中间件真正的实现机制、运行时序还不能做到完全的理解。
97 0
|
中间件 数据库
多个koa中间件执行顺序
多个中间件执行顺序 多个中间件会形成一个栈结构(middle stack),以"先进后出"(first-in-last-out)的顺序执行。 最外层的中间件首先执行。
2426 1
|
4月前
|
消息中间件 存储 负载均衡
消息中间件的选择:RabbitMQ是一个明智的选择
消息中间件的选择:RabbitMQ是一个明智的选择
87 0
|
3月前
|
消息中间件 存储 中间件
【消息中间件】详解三大MQ:RabbitMQ、RocketMQ、Kafka
【消息中间件】详解三大MQ:RabbitMQ、RocketMQ、Kafka
420 0
|
2月前
|
消息中间件 编解码 Docker
Docker部署RabbitMQ消息中间件
【7月更文挑战第4天】Docker部署RabbitMQ消息中间件
236 3