原生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 } ;
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
} ;
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
} ;
config.js
其它模块 服务器基本信息配置
module. exports = { root : process. cwd ( ) , host : '127.0.0.1' , port : '3008'
} ;
其实这就是node框架express做的事情 封装服务器有着比较繁琐的过程, 这只是一个简单的模型演示, 比如需要封装上传文件的接口, 你可以用到第三方库multiparty, 需要处理ajax跨域, 你可以封装一个前面学的跨域处理函数 : -)