Node.js搭建WEB服务器的示例代码


Posted in Javascript onAugust 15, 2018

前言

这几天为了熟悉vue.js框架,还有webpack的使用,就准备搭建一个发布和浏览markdwon的简单WEB应用。原本是想着用bash脚本和busybox的httpd来作为后台服务,但是bash脚本解析和生成JSON非常不方便,而用Java语言写又觉得部署不方便,所以就想到了正在用到的Node.js,于是就有了这篇博文。(文末有本文代码的github地址)

简单例子

首先,从搭建最简单的 Hello world 开始,建立以下目录、文件和内容。

建立项目及运行

project

web-server
+ | - server.js

server.js

const http = require('http');

http.createServer(function(request, response) {
 // 设置响应头
 response.writeHeader(200, {
  "Content-Type" : "text/plain"
 });
 // 响应主体为 "Hello world!"
 response.write("Hello world!");
 response.end();
})
// 设置监听端口为9000
.listen(9000);

现在,在项目目录运行下面命令来执行 server.js ,浏览器地址栏中输入 localhost:9000 ,如果一切访问都正常,浏览器就会显示 Hello world! 。

node server.js

提示:使用 ctrl+c 停止脚本运行。

至此一个简单例子就运行成功了,下面来分析一下代码。

代码分析

首先, server.js 中引入了Node.js的 http模块 ,它提供了非常底层HTTP API支持。这里使用 createServer() 方法,它返回一个 http.server 实例,使用该实例的 listen() 方法来设置监听端口。

方法 createSever() 中填写的参数是一个函数,该函数会作为回调函数自动添加到 request事件 去,其参数类型分别为 http.IncomingMessage 和 http.ServerResponse 。在回调函数体里,利用 http.ServerResponse 的方法设置了响应头和响应主体,最后以 end() 方法结束本次请求。

路由功能

上述的例子仅仅实现了简单请求响应功能,现在增加路由的功能来健壮我们的WEB服务器。现在,修改为以下的目录、文件和内容。

实现简单路由

project

web-server
 | - server.js
+ | - router.js

server.js

const http = require('http');
const router = require('./router.js');

function handleHello(request, response) {
 // 设置响应头
 response.writeHeader(200, {
  "Content-Type" : "text/plain"
 });
 // 响应主体为 "Hello world!"
 response.write("Hello world!");
 response.end();
}

http.createServer(function(request, response) {
 // 注册路径和其对应回调函数
 router.register(request, response, [
  {
   'url': '/hello',
   'handler': handleHello
  }
 ]);
})
// 设置监听端口为9000
.listen(9000);

router.js

const url = require('url');

exports.register = function(request, response, mapping) {
 // 解析请求路径
 var pathName = url.parse(request.url).pathname;
 // 执行相应请求路径的回调函数
 for(let i = 0, len = mapping.length;i < len;i++) {
  if(mapping[i].url === pathName) {
   mapping[i].handler(request, response);
   return;
  }
 }
 // 请求路径不存在返回404页面
 response.writeHeader(404, {
  "Content-Type" : "text/html"
 });
 response.end(`
  <html>
   <head>
    <title>NOT FOUND</title>
   </head>
   <body>
    <h1>404 NOT FOUND</h1>
   </body>
  </html>
 `);
}

现在,再次执行 server.js 脚本,接着浏览器访问 localhost:9000\hello 会得到 Hello world! 的结果,而访问其他路径则会得到404页面。

这个功能的核心实现是在 router.js 中,通过请求路径的解析,然后根据预先注册好的 mapping 数组,找到与之对应的路径并执行相应的回调函数。

静态资源请求

当前的路由功能只能实现回调函数的执行,而一个WEB服务器应具有响应静态资源请求的能力,接下我们继续来改造它。现在,保持 server.js 内容不变,只改变 router.js 中的内容(部分代码内容省略)。

route.js

const url = require('url');
const path = require('path');
const fs = require('fs');

function getErrorInfo(errorType) {
 // 省略代码
}

function writeErrorPage(response, errorType) {
 // 省略代码
}

exports.register = function(request, response, mapping) {
 // 解析请求路径
 var pathName = url.parse(request.url).pathname;
 // 执行相应请求路径的回调函数
 for(let i = 0, len = mapping.length;i < len;i++) {
  if(mapping[i].url === pathName) {
   mapping[i].handler(request, response);
   return;
  }
 }
 // 请求路径为文件返回文件内容
 var file = path.resolve(__dirname, '.' + pathName);
 fs.exists(file, function(exists) {
  // 请求路径不存在返回404页面
  if(!exists) {
   writeErrorPage(response, 'NOT_FOUND');
  }
  else {
   var stat = fs.statSync(file);
   // 请求路径为目录返回403页面
   if(stat.isDirectory()) {
    writeErrorPage(response, 'FORBIDDEN');
   }
   else {
    response.writeHeader(200, {
     "Content-Type" : "text/html"
    });
    response.end(
     fs.readFileSync(file, 'utf-8')
    );
   }
  }
 });
}

将静态资源请求的行为置后的设计,是为了保证回调函数一定能执行。当静态资源不存在时,应当返回不存在的错误,同时也设置了禁止目录的访问的规则。

后话

现在,只是实现了WEB服务器基本的功能,它还有很大的改进空间。我将项目开源到 github 上,有兴趣的可以克隆下来。希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jQuery版仿Path菜单效果
Dec 15 Javascript
JS判断客服QQ号在线还是离线状态的方法
Jan 13 Javascript
JavaScript 实现完美兼容多浏览器的复制功能代码
Apr 28 Javascript
JS实现按比例缩放图片的方法(附C#版代码)
Dec 08 Javascript
jQuery拖拽排序插件制作拖拽排序效果(附源码下载)
Feb 23 Javascript
基于jquery编写的放大镜插件
Mar 23 Javascript
jQuery+CSS实现一个侧滑导航菜单代码
May 09 Javascript
jQuery验证插件validate使用详解
May 11 Javascript
JS只能输入正整数的简单实例
Oct 07 Javascript
javaScript嗅探执行神器-sniffer.js
Feb 14 Javascript
Angular4表单验证代码详解
Sep 03 Javascript
vantUI 获得piker选中值的自定义ID操作
Nov 04 Javascript
Layui 设置select下拉框自动选中某项的方法
Aug 14 #Javascript
vue升级之路之vue-router的使用教程
Aug 14 #Javascript
layui table 参数设置方法
Aug 14 #Javascript
layui 表格的属性的显示转换方法
Aug 14 #Javascript
JS中数组与对象的遍历方法实例小结
Aug 14 #Javascript
layui实现table加载的示例代码
Aug 14 #Javascript
layui点击导航栏刷新tab页的示例代码
Aug 14 #Javascript
You might like
使用Sphinx对索引进行搜索
2013/06/25 PHP
php共享内存段示例分享
2014/01/20 PHP
PHP实现链式操作的核心思想
2015/06/23 PHP
详解WordPress开发中的get_post与get_posts函数使用
2016/01/04 PHP
PHP面向对象程序设计之命名空间与自动加载类详解
2016/12/02 PHP
CSS常用网站布局实例
2008/04/03 Javascript
锋利的jQuery 要点归纳(二) jQuery中的DOM操作(下)
2010/03/23 Javascript
javascript中最常用的继承模式 组合继承
2010/08/12 Javascript
javascript跨域刷新实现代码
2011/01/01 Javascript
javascript跑马灯悬停放大效果实现代码
2012/12/12 Javascript
Ext修改GridPanel数据和字体颜色、css属性等
2014/06/13 Javascript
Jquery对select的增、删、改、查操作
2015/02/06 Javascript
再谈JavaScript线程
2015/07/10 Javascript
pace.js页面加载进度条插件
2015/09/29 Javascript
discuz表情的JS提取方法分析
2017/03/22 Javascript
js实现无刷新监听URL的变化示例代码详解
2020/06/03 Javascript
[03:16]DOTA2完美大师赛主赛事首日集锦
2017/11/23 DOTA
Python中用Descriptor实现类级属性(Property)详解
2014/09/18 Python
Python greenlet实现原理和使用示例
2014/09/24 Python
python基于Tkinter库实现简单文本编辑器实例
2015/05/05 Python
SELENIUM自动化模拟键盘快捷键操作实现解析
2019/10/28 Python
Python利用PyExecJS库执行JS函数的案例分析
2019/12/18 Python
美国狗旅行和户外用品领先供应商:kurgo
2020/08/18 全球购物
C++的几个面试题附答案
2016/08/03 面试题
护士演讲稿范文
2014/01/05 职场文书
会计专业应届生自荐信
2014/02/07 职场文书
综合实践活动方案
2014/02/14 职场文书
信息科学与技术专业求职信范文
2014/02/20 职场文书
乡村文明行动实施方案
2014/03/29 职场文书
艺术设计专业毕业生推荐信
2014/07/08 职场文书
个性与发展自我评价
2015/03/06 职场文书
小学教学工作总结2015
2015/05/13 职场文书
Golang 空map和未初始化map的注意事项说明
2021/04/29 Golang
Python游戏开发实例之graphics实现AI五子棋
2021/11/01 Python
vue使用localStorage持久性存储实现评论列表
2022/04/14 Vue.js
SQL使用复合索引实现数据库查询的优化
2022/05/25 SQL Server