- 原生node封装一个简易的服务器, 把前面几天的知识揉和起来做一个服务器
- 基础实现, 首页访问, 静态资源服务器, 特定接口封装, 404
app.js
服务器入口文件 app.js node app.js即可启动服务器
const { start } = require('./modules/server');
start();
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
};
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 };
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
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
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(`
index
欢迎~
`);
}
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(`
404
not find
`);
}
function serverError(req, res, pathname) {
res.writeHeader(500, { 'content-type': 'text/html;charset=utf-8' });
res.end(`
500
server error
`);
}
module.exports = {
staticHanlder,
indexHanlder,
tableHanlder,
notFind,
serverError
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
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
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
config.js
其它模块 服务器基本信息配置
module.exports = {
root: process.cwd(),
host: '127.0.0.1',
port: '3008'
};
- 其实这就是node框架express做的事情 封装服务器有着比较繁琐的过程, 这只是一个简单的模型演示, 比如需要封装上传文件的接口, 你可以用到第三方库multiparty, 需要处理ajax跨域, 你可以封装一个前面学的跨域处理函数 :-)