基本功能

不急着写下第一行代码,而是先梳理一下就基本功能而言有哪些步骤。

  1. 在本地根据指定端口启动一个http server,等待着来自客户端的请求
  2. 当请求抵达时,根据请求的url,以设置的静态文件目录为base,映射得到文件位置
  3. 检查文件是否存在
  4. 如果文件不存在,返回404状态码,发送not found页面到客户端
  5. 如果文件存在:
    • 打开文件待读取
    • 设置response header
    • 发送文件到客户端
  6. 等待来自客户端的下一个请求

实现基本功能

代码结构

创建一个nodejs-static-webserver目录,在目录内运行npm init初始化一个package.json文件。

mkdir nodejs-static-webserver && cd "$_"
// initialize package.json
npm init

接着创建如下文件目录:

-- config
---- default.json
-- static-server.js
-- app.js

default.json

{
"port": 9527,
"root": "/Users/sheila1227/Public",
"indexPage": "index.html"
}

default.js存放一些默认配置,比如端口号、静态文件目录(root)、默认页(indexPage)等。当这样的一个请求http://localhost:9527/myfiles/抵达时. 如果根据root映射后得到的目录内有index.html,根据我们的默认配置,就会给客户端发回index.html的内容。

static-server.js

const http = require('http');
const path = require('path');
const config = require('./config/default'); class StaticServer {
constructor() {
this.port = config.port;
this.root = config.root;
this.indexPage = config.indexPage;
} start() {
http.createServer((req, res) => {
const pathName = path.join(this.root, path.normalize(req.url));
res.writeHead(200);
res.end(`Requeste path: ${pathName}`);
}).listen(this.port, err => {
if (err) {
console.error(err);
console.info('Failed to start server');
} else {
console.info(`Server started on port ${this.port}`);
}
});
}
} module.exports = StaticServer;

在这个模块文件内,我们声明了一个StaticServer类,并给其定义了start方法,在该方法体内,创建了一个server对象,监听rquest事件,并将服务器绑定到配置文件指定的端口。在这个阶段,我们对于任何请求都暂时不作区分地简单地返回请求的文件路径。path模块用来规范化连接和解析路径,这样我们就不用特意来处理操作系统间的差异。

app.js

const StaticServer = require('./static-server');

(new StaticServer()).start();

在这个文件内,调用上面的static-server模块,并创建一个StaticServer实例,调用其start方法,启动了一个静态资源服务器。这个文件后面将不需要做其他修改,所有对静态资源服务器的完善都发生在static-server.js内。

在目录下启动程序会看到成功启动的log:

> node app.js

Server started on port 9527

在浏览器中访问,可以看到服务器将请求路径直接返回了。

路由处理

之前我们对任何请求都只是向客户端返回文件位置而已,现在我们将其替换成返回真正的文件:

    routeHandler(pathName, req, res) {

    }

    start() {
http.createServer((req, res) => {
const pathName = path.join(this.root, path.normalize(req.url));
this.routeHandler(pathName, req, res);
}).listen(this.port, err => {
...
});
}

将由routeHandler来处理文件发送。

读取静态文件

读取文件之前,用fs.stat检测文件是否存在,如果文件不存在,回调函数会接收到错误,发送404响应。

   respondNotFound(req, res) {
res.writeHead(404, {
'Content-Type': 'text/html'
});
res.end(`<h1>Not Found</h1><p>The requested URL ${req.url} was not found on this server.</p>`);
} respondFile(pathName, req, res) {
const readStream = fs.createReadStream(pathName);
readStream.pipe(res);
} routeHandler(pathName, req, res) {
fs.stat(pathName, (err, stat) => {
if (!err) {
this.respondFile(pathName, req, res);
} else {
this.respondNotFound(req, res);
}
});
}

Note:

读取文件,这里用的是流的形式createReadStream而不是readFile,是因为后者会在得到完整文件内容之前将其先读到内存里。这样万一文件很大,再遇上多个请求同时访问,readFile就承受不来了。使用文件可读流,服务端不用等到数据完全加载到内存再发回给客户端,而是一边读一边发送分块响应。这时响应里会包含如下响应头:

Transfer-Encoding:chunked

默认情况下,可读流结束时,可写流的end()方法会被调用。

node 静态伺服(搭建服务)的更多相关文章

  1. node.js简单搭建服务,访问本地站点文件

    1.安装nodejs服务(从官网下载安装),node相当于apache服务器 2.在自己定义的目录下新建服务器文件如 server.js 例如,我在D:\nodeJs下创建了server.js文件 v ...

  2. 绝版Node--Sequlize搭建服务(Node全栈之路)

    绝版Node--Sequlize搭建服务(Node全栈之路) 参考资料:https://itbilu.com/nodejs/npm/VkYIaRPz-.html 准备环境:Mysql,Node 前沿: ...

  3. 使用node搭建服务时,服务可以启动,但是无法访问

    一开始搭建的是没有问题,能够正常启动和访问,然后吃了个饭回来就变成只能启动,浏览器访问不了了. 说真的,这是一个常识问题.使用node搭建服务访问本地文件,服务搭建的没有问题,能够正常启动.但是在浏览 ...

  4. 使用node+puppeteer+express搭建截图服务

    使用node+puppeteer+express搭建截图服务 转载请注明出处https://www.cnblogs.com/funnyzpc/p/14222807.html 写在之前 一开始我们的需求 ...

  5. 《JERRY Hexo & GitHub 静态网站搭建说明》

    JERRY-Hexo-GitHub <JERRY Hexo & GitHub 静态网站搭建说明> 原创内容,转载请注明出处! 一.前言 1.1 什么是 Hexo? 一个基于 Nod ...

  6. paip.最好的脚本语言node js 环境搭建连接mysql

    paip.最好的脚本语言node js 环境搭建连接mysql #====下载node...走十一个exe..容易的.. 1 #0----Hello world   .js 2 #---------模 ...

  7. CAS 5.1.x 的搭建和使用(二)—— 通过Overlay搭建服务端-其它配置说明

    CAS单点登录系列: CAS 5.1.x 的搭建和使用(一)—— 通过Overlay搭建服务端 CAS5.1.x 的搭建和使用(二)—— 通过Overlay搭建服务端-其它配置说明 CAS5.1.x ...

  8. Node.js环境搭建&&npm安装

    Node.js环境搭建 什么使Node.js呢?我们知道JavaScript开始作为客户端语言,但早已在浏览器端一统江湖,这时,野心越来越大,它就想向服务器端拓展了,于是Node.js就是这样的,我们 ...

  9. Node.js发布http服务

    Node.js发布http服务 2018-11-09 09:43:03   Visit  0 简单服务 var http = require(\'http\'); http.createServer( ...

随机推荐

  1. Java读取文件加锁代码Demo(利用Java的NIO)

    本博文部分转载于:http://blog.csdn.net/wangbaochu/article/details/48546717 Java 提供了文件锁FileLock类,利用这个类可以控制不同程序 ...

  2. django2笔记:路由path语法

    django2笔记:路由path语法 9月23,Django 发布了2.0a1版本,这是一个 feature freeze 版本,如果没有什么意外的话,2.0正式版不会再增加新的功能了.按照以往的规律 ...

  3. VMWare Workstation 11的安装

    不多说,直接上干货! 说白了   VMWare Workstation是收费的! VMware Player 和 VirtualBox是免费的! 虚拟机软件可让你在一个操作系统上直接运行的多个不同的虚 ...

  4. Resolve类中错误体系的处理

    标红的表示要走3步骤,也就是: final List<MethodResolutionPhase> methodResolutionSteps = List.of( MethodResol ...

  5. 联系动词Link.V笔记

    这篇单独记录一下联系动词的语法.需要注意的是,只有这个单词在作为联系动词的时候才是这个意思或者才是这样的用法.当然每个单词都会有很多的用法,并不只是这样而已. 第一组:好像…似乎… seem to b ...

  6. Jmeter报错之jmeter.gui.action.ActionRouter: Error processing gui.action.Start@1b7c473a java.lang.ArrayIndexOutOfBoundsException

    一个使用了很久的Jmeter脚本,运行时Jmeter的UI界面上点击绿色按钮后,完全无反应,只有log报错,如下: 2017/06/28 14:29:23 ERROR - jmeter.gui.act ...

  7. 33-hadoop-cdh搭建coudemanager安装

    http://www.aboutyun.com/thread-9219-1-1.html  非常强大的博客 ! ! ! 1, cdh简介 CDH (Cloudera’s Distribution, i ...

  8. centos7 安装配置zookeeper

    https://blog.csdn.net/AaronLin6/article/details/78438877 https://www.cnblogs.com/sxdcgaq8080/p/74924 ...

  9. Solidity遍历

    实际上,映射对于存储地址的标记值非常有用. 我们在许多合约中都看到了它们,它们通常以这种方式定义: mapping (address => uint) public users; 由于映射是公共 ...

  10. Hibernate杂问

    1 谈谈你对ORM框架的基本思想的了解? 首先 ORM是 对象关系映射,是为了解决类似于JDBC实现对象持久化的问题开发的. 框架的基本特征:完成面向对象的编程语言到关系数据库之间的映射. 他的映射分 ...