全栈05 静态文件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/duola8789/article/details/83149275

简介

静态文件就是无需经过数据库、模版渲染等步骤就直接呈献给用户各种文件

一般来说,访问静态文件的url和其本身的文件路径是一样的,比如http://a.com/public/img/a.png,那在a.com的文件路径下面就会有public文件夹。

每个http响应头里面都有Content-Type字段,该字段告诉浏览器返回的文件是什么类型的,便于浏览器处理。比如html文件的Content-Typetext/html,而一般的文本的Content-Typetext/plain,如果将一个html文件的Content-Type改为text/plain,那么浏览器不会解析html文件,而是直接输出html代码

koa-static

koa-static是koa实现静态资源访问的中间件,基本用法如下:

'use strict';

const app = require('koa')();
const server = require('koa-static');

const opts = {
  maxage: 1000 * 60 * 60 * 24 * 365, // 1年,默认为0
  hidden: false, // 能否返回隐藏文件(以`.`打头),默认false不返回
  index: 'index.js', // 默认文件名
  defer: true, // 在yield* next之后返回静态文件,默认在之前
  gzip: true 
  // 允许传输gzip,如静态文件夹下有两个文件,index.js和index.js.gz,
  // 会优先传输index.js.gz,默认开启
};

app.use(server('/public', opts));

koa-static中的核心模块是koa-send模块,如果开启了gzip就会有限传输.gz文件

if (encoding === 'gzip' && gzip && (yield fs.exists(path + '.gz'))) {
  path = path + '.gz';
  ctx.set('Content-Encoding', 'gzip');
  ctx.res.removeHeader('Content-Length');
}

核心代码:

ctx.set('Content-Length', stats.size);
if (!ctx.response.get('Last-Modified')) {
  ctx.set('Last-Modified', stats.mtime.toUTCString());
}
if (!ctx.response.get('Cache-Control')) {
  ctx.set('Cache-Control', 'max-age=' + (maxage / 1000 | 0));
}
ctx.type = type(path);
ctx.body = fs.createReadStream(path);

实战

一个简单的需求,服务A是一个静态博客网站,由Nginx提供HTTP服务(80端口),代码仓库为GitA。当向GitA中提交新的文件时,会触发Gitlab的Webhook的Push Events,向另一个端口8888提交一个POST请求。

服务B利用NodeJS,监听了8016端口,当收到webhook触发的POST请求后,会进行一些列的动作,拉取GitA中代码,清空文件夹,利用Hexo进行编译,将编译好的文件提供给服务A使用。

最终采用的方案是有Node完成两个服务的提供,使用了Koa,并且不再8016端口上监听编译请求,降低复杂度(实际上监听另外的端口也是可以的,只要再生成一个koa的实例,监听对应的端口就可以了)

值得一提的是404页面,因为没有采用koa-router,所以需要通过ctx.status手动判断状态,然后使用fs.createReadStream读取对应html文件,并且将ctx.type设置为html,作为404页面返回。

当监听一个端口的时候,中间件可以有多个,要注意顺序,从上至下,如果上面的中间件匹配的话,就不再向下继续匹配,所以404页面的匹配要放在最下面。

var fs = require("fs");
var path = require("path");
var process = require("child_process");
var Koa = require("koa");
var KoaBodyParser = require("koa-bodyparser");
var Compress = require("koa-compress");
var staticServer = require("koa-static");

// 编译发布过程
var publishLock = false;

function doPublish() {
  // 编译过程
}

var app = new Koa();

app.use(Compress({
  threshold: 2048 // 要压缩的最小响应字节
}));

app.use(KoaBodyParser());

// Koa静态文件服务
app.use(staticServer(path.resolve("public")));

// 特殊页面
app.use(function (ctx) {
  // 404页面
  if (~[403, 404, 405].indexOf(ctx.status)) {
    ctx.type = "html";
    ctx.body = fs.createReadStream("./public/404.html");
  }

  // 仅仅是POST请求的特殊路由被处理
  if (ctx.method === "POST" && ctx.path === "/bebmbp8") {
    ctx.type = "text/plain";
    ctx.body = "Blog Publish...";
    ctx.status = 200;
    doPublish();
  }
});

// 监听80端口,返回静态文件
app.listen(80, function () {
  console.log("blog-app start at 80.", new Date());
});

//服务器重启之后,开始一次编译
setTimeout(doPublish, 1000);

参考

猜你喜欢

转载自blog.csdn.net/duola8789/article/details/83149275