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 相关文章推荐
Prototype Function对象 学习
Jul 12 Javascript
js格式化金额可选是否带千分位以及保留精度
Jan 28 Javascript
JavaScript运行时库属性一览表
Mar 14 Javascript
js实现文字跟随鼠标移动而移动的方法
Feb 28 Javascript
jQuery仿Flash上下翻动的中英文导航菜单实例
Mar 10 Javascript
javascript实现input file上传图片预览效果
Dec 31 Javascript
jQuery Easyui datagrid连续发送两次请求问题
Dec 13 Javascript
jQuery ajax动态生成table功能示例
Jun 14 jQuery
react-router v4如何使用history控制路由跳转详解
Jan 09 Javascript
js删除数组中的元素delete和splice的区别详解
Feb 03 Javascript
jQuery实现html可联动的百分比进度条
Mar 26 jQuery
JS Canvas接口和动画效果大全
Apr 29 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
使用PHP会话(Session)实现用户登陆功能
2013/06/29 PHP
PHP PDOStatement::setFetchMode讲解
2019/02/03 PHP
Yii框架实现对数据库的CURD操作示例
2019/09/03 PHP
jQuery+CSS 实现随滚动条增减的汽水瓶中的液体效果
2011/09/26 Javascript
png在IE6 下无法透明的解决方法汇总
2015/05/21 Javascript
BootStrap和jQuery相结合实现可编辑表格
2016/04/21 Javascript
超实用的javascript时间处理总结
2016/08/16 Javascript
jQuery ajax MD5实现用户注册即时验证功能
2016/10/11 Javascript
微信小程序 location API接口详解及实例代码
2016/10/12 Javascript
WEB开发之注册页面验证码倒计时代码的实现
2016/12/15 Javascript
React Native实现地址挑选器功能
2017/10/24 Javascript
基于vue.js实现的分页
2018/03/13 Javascript
vue自定义指令的创建和使用方法实例分析
2018/12/04 Javascript
微信小程序云开发实现增删改查功能
2019/05/17 Javascript
解决vuex数据异步造成初始化的时候没值报错问题
2019/11/13 Javascript
vue中使用echarts的示例
2021/01/03 Vue.js
[07:40]DOTA2每周TOP10 精彩击杀集锦vol.4
2014/06/25 DOTA
[01:25:38]DOTA2-DPC中国联赛 正赛 VG vs LBZS BO3 第一场 1月19日
2021/03/11 DOTA
Python判断变量是否为Json格式的字符串示例
2017/05/03 Python
python利用urllib实现爬取京东网站商品图片的爬虫实例
2017/08/24 Python
Python中enumerate函数代码解析
2017/10/31 Python
python smtplib模块自动收发邮件功能(一)
2018/05/22 Python
python 字典套字典或列表的示例
2019/12/16 Python
Python文本处理简单易懂方法解析
2019/12/19 Python
浅析Python 字符编码与文件处理
2020/09/24 Python
美国当红的名品折扣网:Gilt Groupe
2016/08/15 全球购物
英国经典球衣网站:Classic Football Shirts
2017/05/20 全球购物
意大利制造的男鞋和女鞋:SCAROSSO
2018/03/07 全球购物
董事长助理工作职责
2014/06/08 职场文书
2014年公务员个人工作总结
2014/11/22 职场文书
怀孕辞职信怎么写
2015/02/28 职场文书
2019暑假阅读倡议书
2019/06/24 职场文书
有关花店创业的计划书模板
2019/08/27 职场文书
导游词之上饶龟峰
2019/10/25 职场文书
MySQL之PXC集群搭建的方法步骤
2021/05/25 MySQL
Vue的生命周期一起来看看
2022/02/24 Vue.js