前言

狭义中间件 请求/拦截,最典型的场景是 Koa.js 传输静态文件中间件的实现koa-send。Koa.js 官方对 koa-send 进行二次封装,推出了koa-static 中间件,目标是用于做静态服务器或者项目静态资源管理。

本节主要以官方的 koa-static 中间件为参考,基于上一节实现的最简单koa-send, 实现了一个最简单的koa-static 中间件,方便原理讲解和后续二次自定义优化开发。

实现步骤

  • step 01 配置静态资源绝对目录地址
  • step 02 判断是否支持等待其他请求
  • step 03 判断是否为 GET 和 HEAD 类型的请求
  • step 04 通过koa-send 中间件读取和返回静态文件

    实现源码

    demo源码
    https://github.com/chenshenhai/koajs-design-note/tree/master/demo/chapter-04-03

    1. ## 安装依赖
    2. npm i
    3. ## 执行 demo
    4. npm run start
    5. ## 最后启动chrome浏览器访问
    6. ## http://127.0.0.1:3000/index.html

    koa-static 依赖

    koa-send 中间件,这里只用了上一节实现的最简单koa-send

    koa-static 解读

    1. const {resolve} = require('path');
    2. const send = require('./send');
    3. function statics(opts = {
    4. root: ''
    5. }) {
    6. opts.root = resolve(opts.root);
    7. // 是否需要等待其他请求
    8. if (opts.defer !== true) {
    9. // 如果需要等待其他请求
    10. return async function statics(ctx, next) {
    11. let done = false;
    12. if (ctx.method === 'HEAD' || ctx.method === 'GET') {
    13. try {
    14. await send(ctx, ctx.path, opts);
    15. done = true;
    16. } catch (err) {
    17. if (err.status !== 404) {
    18. throw err;
    19. }
    20. }
    21. }
    22. if (!done) {
    23. await next();
    24. }
    25. };
    26. } else {
    27. // 如果不需要等待其他请求
    28. return async function statics(ctx, next) {
    29. await next();
    30. if (ctx.method !== 'HEAD' && ctx.method !== 'GET') {
    31. return;
    32. }
    33. if (ctx.body != null || ctx.status !== 404) {
    34. return;
    35. }
    36. try {
    37. await send(ctx, ctx.path, opts);
    38. } catch (err) {
    39. if (err.status !== 404) {
    40. throw err;
    41. }
    42. }
    43. };
    44. }
    45. }
    46. module.exports = statics;

    koa-static 使用

    1. const path = require('path');
    2. const Koa = require('koa');
    3. const statics = require('./index');
    4. const app = new Koa();
    5. const root = path.join(__dirname, './public');
    6. app.use(statics({ root }));
    7. app.use(async(ctx, next) => {
    8. if (ctx.path === '/hello') {
    9. ctx.body = 'hello world';
    10. }
    11. });
    12. app.listen(3000);
    13. console.log('listening on port 3000');

    附录

    参考

  • https://github.com/koajs/static