node 第十天 原生node封装一个简易的服务器

  1. 原生node封装一个简易的服务器, 把前面几天的知识揉和起来做一个服务器
  2. 基础实现, 首页访问, 静态资源服务器, 特定接口封装, 404
  3. app.js 服务器入口文件 app.js node app.js即可启动服务器
const { start } = require('./modules/server');
start();
  1. require_modules.js 整合模块导出
const url = require('url');
const path = require('path');
const http = require('http');
const querystring = require('querystring');
const fs = require('fs');
const multiparty = require('multiparty');

module.exports = {
  url,
  path,
  http,
  querystring,
  fs,
  multiparty
};

  1. server.js server 启动模块
const { http } = require('./require_modules');
const { port, host } = require('./config');
const { route } = require('./router');

function start() {
  const server = http.createServer((req, res) => {
    route(req, res);
  });
  server.listen(port, host, () => {
    console.log(`server listening in http://${host}:${port}`);
  });
}
module.exports = { start };

  1. router.js 路由模块, 以及接口处理函数对照表
const { url } = require('./require_modules');
const { host, port } = require('./config');
const { staticHanlder, indexHanlder, tableHanlder, notFind } = require('./hanlder');
const hanlder = {
  '/index': indexHanlder,
  '/static': staticHanlder,
  '/index': indexHanlder,
  '/getTableData': tableHanlder,
  404: notFind
};
const route = (req, res) => {
  const thisURL = new URL(`http://${host}:${port}${req.url}`);
  let pathname = thisURL.pathname;
  if (pathname === '/') {
    pathname = '/index/';
  }
  const thisHanlder =
    Object.entries(hanlder).find(([key, val]) => {
      let reg = new RegExp(`^${key}/.*`);
      return reg.test(pathname);
    })?.[1] ?? hanlder[404];

  thisHanlder(req, res, pathname);
};
module.exports = { route };
  1. hanlder.js 接口处理函数模块
const { fs, path, querystring } = require('../modules/require_modules');
const { getMimeType } = require('../modules/mime_type');
const { root } = require('./config');
const { host, port } = require('./config');

function staticHanlder(req, res, pathname) {
  res.writeHeader(200, { 'content-type': getMimeType(pathname) });

  const filePath = path.join(root, pathname);

  fs.stat(filePath, (err, stats) => {
    if (err) {
      notFind(req, res, pathname);
      return;
    }
    if (!stats) {
      notFind(req, res, pathname);
      return;
    }
    if (stats.isDirectory()) {
      notFind(req, res, pathname);
      return;
    }
    if (stats.isFile()) {
      fs.readFile(filePath, (err, data) => {
        if (err) {
          notFind(req, res, pathname);
        }
        res.writeHeader(200, { 'content-type': getMimeType(pathname) });
        res.end(data);
      });
      return;
    }
  });
}
function indexHanlder(req, res, pathname) {
  res.writeHeader(200, { 'content-type': 'text/html;charset=utf-8' });
  res.end(`<!DOCTYPE html>
  <html lang="en">
    <head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <title>index</title>
    </head>
    <body>
      <h1>欢迎~</h1>
    </body>
  </html>`);
}
function tableHanlder(req, res, pathname) {
  const thisURL = new URL(`http://${host}:${port}${req.url}`);
  let search = thisURL.search.replace('?', '');
  const searchInfo = querystring.parse(search);
  let start = Number(searchInfo.start) || 0;
  let end = Number(searchInfo.end) || start + 10;
  const jsonPath = path.join(root, '/data/table.json');
  fs.readFile(jsonPath, (err, data) => {
    if (err) {
      notFind(req, res, pathname);
      return;
    }
    const jsonData = JSON.parse(data.toString('utf-8'));
    const resData = jsonData.slice(start, end);
    res.writeHeader(200, { 'content-type': 'application/json;charset=utf-8' });
    res.end(JSON.stringify(resData));
  });
}

function notFind(req, res, pathname) {
  res.writeHeader(404, { 'content-type': 'text/html;charset=utf-8' });
  res.end(`<!DOCTYPE html>
  <html lang="en">
    <head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <title>404</title>
    </head>
    <body>
      <h1>not find</h1>
    </body>
  </html>`);
}
function serverError(req, res, pathname) {
  res.writeHeader(500, { 'content-type': 'text/html;charset=utf-8' });
  res.end(`<!DOCTYPE html>
  <html lang="en">
    <head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <title>500</title>
    </head>
    <body>
      <h1>server error</h1>
    </body>
  </html>`);
}
module.exports = {
  staticHanlder,
  indexHanlder,
  tableHanlder,
  notFind,
  serverError
};
  1. mime_type.js 其它模块, 用于获取媒体文件类型
const { path } = require('../modules/require_modules');
const MIME_TYPE = {
  css: 'text/css',
  gif: 'image/gif',
  html: 'text/html',
  ico: 'image/x-icon',
  jpeg: 'image/jpeg',
  jpg: 'image/jpeg',
  js: 'text/javascript',
  json: 'application/json',
  pdf: 'application/pdf',
  png: 'image/png',
  svg: 'image/svg+xml',
  swf: 'application/x-shockwave-flash',
  tiff: 'image/tiff',
  txt: 'text/plain',
  wav: 'audio/x-wav',
  wma: 'audio/x-ms-wma',
  wmv: 'video/x-ms-wmv',
  xml: 'text/xml'
};

function getMimeType(pathname) {
  let ext = path.extname(pathname).replace('.', '').toLowerCase();
  if (!ext) {
    ext = pathname;
  }
  return MIME_TYPE[ext] || MIME_TYPE['txt'];
}
module.exports = {
  getMimeType
};
  1. config.js 其它模块 服务器基本信息配置
module.exports = {
  root: process.cwd(),
  host: '127.0.0.1',
  port: '3008'
};
  1. 其实这就是node框架express做的事情 封装服务器有着比较繁琐的过程, 这只是一个简单的模型演示, 比如需要封装上传文件的接口, 你可以用到第三方库multiparty, 需要处理ajax跨域, 你可以封装一个前面学的跨域处理函数 :-)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值