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实现的图片在各种分辨率下未知的容器内上下左右居中
May 11 Javascript
node.js正则表达式获取网页中所有链接的代码实例
Jun 03 Javascript
jQuery+PHP星级评分实现方法
Oct 02 Javascript
jQuery Ajax前后端使用JSON进行交互示例
Mar 17 Javascript
JavaScript中在光标处插入添加文本标签节点的详细方法
Mar 22 Javascript
用Axios Element实现全局的请求loading的方法
Mar 15 Javascript
jquery.param()实现数组或对象的序列化方法
Oct 08 jQuery
微信小程序顶部导航栏滑动tab效果
Jan 28 Javascript
mpvue开发音频类小程序踩坑和建议详解
Mar 12 Javascript
使用Node.js在深度学习中做图片预处理的方法
Sep 18 Javascript
vue键盘事件点击事件加native操作
Jul 27 Javascript
Vue3中的Refs和Ref详情
Nov 11 Vue.js
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的ob_start();控制您的浏览器cache!
2007/02/14 PHP
php设计模式 Strategy(策略模式)
2011/06/26 PHP
PHP include_path设置技巧分享
2011/07/03 PHP
php后台多用户权限组思路与实现程序代码分享
2012/02/13 PHP
PHP5权威编程阅读学习笔记 附电子书下载
2012/07/05 PHP
解析PHP工厂模式的好处
2013/06/18 PHP
php版微信开发之接收消息,自动判断及回复相应消息的方法
2016/09/23 PHP
PHP空值检测函数与方法汇总
2017/11/19 PHP
用JavaScript调用WebService的示例
2008/04/07 Javascript
Javascript 匿名函数及其代码模式原理
2010/03/19 Javascript
编写针对IE的JS代码两种编写方法
2013/01/30 Javascript
js中事件的处理与浏览器对象示例介绍
2013/11/29 Javascript
javascript判断图片是否加载完成的方法推荐
2016/05/13 Javascript
干货!教大家如何选择Vue和React
2017/03/13 Javascript
详解node HTTP请求客户端 - Request
2017/05/05 Javascript
详解如何构建Angular项目目录结构
2017/07/13 Javascript
vue实现仿淘宝结账页面实例代码
2017/11/08 Javascript
vue awesome swiper异步加载数据出现的bug问题
2018/07/03 Javascript
Vue实现商品飞入购物车效果(电商项目)
2019/11/26 Javascript
Js逆向实现滑动验证码图片还原的示例代码
2020/03/10 Javascript
Python数据可视化正态分布简单分析及实现代码
2017/12/04 Python
python set内置函数的具体使用
2019/07/02 Python
django 框架实现的用户注册、登录、退出功能示例
2019/11/28 Python
JupyterNotebook设置Python环境的方法步骤
2019/12/03 Python
Python 找出英文单词列表(list)中最长单词链
2020/12/14 Python
德国化妆品和天然化妆品网上商店:kosmetikfuchs.de
2017/06/09 全球购物
北美主要的汽车零部件零售商:AutoShack.com
2019/02/23 全球购物
中科软笔试题和面试题
2014/10/07 面试题
计算机专业个人求职信范例
2013/09/23 职场文书
工厂门卫岗位职责范本
2014/04/04 职场文书
2015年保卫科工作总结
2015/05/14 职场文书
闪闪红星观后感
2015/06/08 职场文书
2016年“5.12”护士节致辞
2015/07/31 职场文书
青年岗位能手事迹材料(2016推荐版)
2016/03/01 职场文书
浅谈PHP7中的一些小技巧
2021/05/29 PHP
CSS font-variation 可变字体的魅力(实例详解)
2022/03/03 HTML / CSS