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的输入框在光标位置插入内容, 并选中
Oct 29 Javascript
JavaScript面向对象程序设计三 原型模式(上)
Dec 21 Javascript
javascript获得网页窗口实际大小的示例代码
Sep 21 Javascript
jquery实现邮箱自动补全功能示例分享
Feb 17 Javascript
JavaScript实现按Ctrl键打开新页面
Sep 04 Javascript
JavaScript+CSS无限极分类效果完整实现方法
Dec 22 Javascript
Javascript中的数组常用方法解析
Jun 17 Javascript
Angular2.js实现表单验证详解
Jun 23 Javascript
微信小程序保存多张图片的实现方法
Mar 05 Javascript
react高阶组件添加和删除props
Apr 26 Javascript
小程序点击图片实现png转jpg
Oct 22 Javascript
使用webpack/gulp构建TypeScript项目的方法示例
Dec 18 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代码
2012/06/08 PHP
举例讲解PHP面对对象编程的多态
2015/08/12 PHP
PHP中Restful api 错误提示返回值实现思路
2016/04/12 PHP
js,jQuery 排序的实现代码,网页标签排序的实现,标签排序
2011/04/27 Javascript
js函数名与form表单元素同名冲突的问题
2014/03/07 Javascript
一个简单的jquery的多选下拉框(自写)
2014/05/05 Javascript
javascript中的正则表达式使用详解
2015/08/30 Javascript
详解nodejs 文本操作模块-fs模块(二)
2016/12/22 NodeJs
基于JavaScript实现屏幕滚动效果
2017/01/18 Javascript
JS实现禁止用户使用Ctrl+鼠标滚轮缩放网页的方法
2017/04/28 Javascript
JavaScript中正则表达式判断匹配规则及常用方法
2017/08/03 Javascript
vue用Object.defineProperty手写一个简单的双向绑定的示例
2018/07/09 Javascript
浅析Vue项目中使用keep-Alive步骤
2018/07/27 Javascript
Js Snowflake(雪花算法)生成随机ID的实现方法
2020/08/26 Javascript
[45:25]完美世界DOTA2联赛循环赛 PXG vs IO 第一场 11.06
2020/11/09 DOTA
python定时器(Timer)用法简单实例
2015/06/04 Python
Python实现简单登录验证
2016/04/13 Python
python中的lambda表达式用法详解
2016/06/22 Python
分享一个简单的python读写文件脚本
2017/11/25 Python
python清除字符串中间空格的实例讲解
2018/05/11 Python
Python逐行读取文件中内容的简单方法
2019/02/26 Python
python程序 线程队列queue使用方法解析
2019/09/23 Python
python3实现用turtle模块画一棵随机樱花树
2019/11/21 Python
使用Tensorflow实现可视化中间层和卷积层
2020/01/24 Python
Django与pyecharts结合的实例代码
2020/05/13 Python
Python+kivy BoxLayout布局示例代码详解
2020/12/28 Python
详解HTML5中垂直上下居中的解决方案
2017/12/20 HTML / CSS
办公室秘书自我鉴定
2014/01/18 职场文书
保护环境倡议书
2014/04/14 职场文书
积极向上的团队口号
2014/06/06 职场文书
小学毕业典礼演讲稿
2014/09/09 职场文书
公务员个人年终总结
2015/02/12 职场文书
酒店办公室主任岗位职责
2015/04/01 职场文书
关于践行三严三实的心得体会
2016/01/05 职场文书
python基于OpenCV模板匹配识别图片中的数字
2021/03/31 Python
OpenCV-Python实现图像平滑处理操作
2021/06/08 Python