0%

底层 HTTP 模块

Express 框架建立在 node.js 内置的 http 模块上,框架的核心是对 HTTP 模块的再包装
http 模块生成服务器的原始代码如下:

1
2
3
4
5
6
7
8
var http = require("http");

var app = http.createServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end(" express hahahah");
});

app.listen(4040, "localhost");

上面的代码关键是 http 模块的 createServer 方法,表示生成一个 http 服务器实例,该方法接受一个回调函数,回调函数的两个参数分别代表 HTTP 请求和 HTTP 响应的 request 对象和 response 对象

上面的代码用 Express 改写如下

1
2
3
4
5
6
7
8
var express = require('express');
var app = express();

app.get('/', function (req, res) {
res.send('Hello world!');
});

app.listen(7000);

可以发现两端代码特别相似,原来是用 http.createServer 方法新建一个 app 实例,现在则是用 Express 的构造方法,生成一个 Epress 实例,两种方法的回调函数都是相同的,
Express 等于在 HTTP 模块之上,加了一个中间层

什么是中间件

中间件就是处理 HTTP 请求的函数,
特点:一个中间件处理完再传递给下一个中间件,APP 实例在运行中会调用一系列的中间件

每个中间件可以从 APP 实例接收三个参数 request (代表 HTTP 请求),response (代表 HTTP 响应),next 回调函数 (代表下一个中间件),每一个中间件都可以对 HTTP 请求 (request 对象) 进行加工,并且决定是否调用 next 方法,将 request 对象再传给下一个中间件

最简单的中间件

1
2
3
4
5
6
7
8
9
10
11
12
function uselessMiddleware(req,res,next){
next()
}

上面代码的next就是下一个中间件。如果它带有参数,则代表抛出一个错误,参数为错误文本。

function uselessMiddleware(req, res, next) {
next('出错了!');
}
抛出错误以后,后面的中间件将不再执行,直到发现一个错误处理函数为止。


use 方法

use 是 express 注册中间件的方法,使用 app.use 方法,注册了两个中间件,收到 HTTP 请求后,先调用第一个中间件,根据 next () 确定是否把 request 对象传递到下一个中间件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var express = require("express");
var http = require("http");

var app = express();

app.use(function(request, response, next) {
console.log("In comes a " + request.method + " to " + request.url);
next();
});

app.use(function(request, response) {
response.writeHead(200, { "Content-Type": "text/plain" });
response.end("Hello world!\n");
});

http.createServer(app).listen(1337);

use 方法内部通过 request.url 的属性可以根据访问路径进行判断,据此就能实现简单的路由,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var express = require("express");
var http = require("http");
var app = express();

app.use(function(request,response,next){
if(request.url == "/"){
response.writeHead(200, { "Content-Type": "text/plain" });
response.end("Welcome to the homepage!\n");
}else{
next();
}
})

app.use(function(request, response, next) {
if (request.url == "/about") {
response.writeHead(200, { "Content-Type": "text/plain" });
} else {
next();
}
});
app.use(function(request, response) {
response.writeHead(404, { "Content-Type": "text/plain" });
response.end("404 error!\n");
});

http.createServer(app).listen(1337);

另外一种比较清晰的方式(上面代码表示,只对根目录的请求,调用某个中间件。

app.use('/path', someMiddleware);
按照这个思想,改造中间件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var express = require("express");
var http = require("http");

var app = express();

app.use("/home", function(request, response, next) {
response.writeHead(200, { "Content-Type": "text/plain" });
response.end("Welcome to the homepage!\n");
});

app.use("/about", function(request, response, next) {
response.writeHead(200, { "Content-Type": "text/plain" });
response.end("Welcome to the about page!\n");
});

app.use(function(request, response) {
response.writeHead(404, { "Content-Type": "text/plain" });
response.end("404 error!\n");
});

http.createServer(app).listen(1337);

参考文档:http://javascript.ruanyifeng.com/nodejs/express.html
Express 是目前最流行的基于 Node.js 的 Web 开发框架,可以快速地搭建一个完整功能的网站。

创建测试项目
mkdir hello-world

进入该目录,新建一个 package.json 文件,内容如下。

1
2
3
4
5
6
7
8
9
10
{
"name": "hello-world",
"description": "hello world test app",
"version": "0.0.1",
"private": true,
"dependencies": {
"express": "4.x"
}
}

安装 express
npm install
执行上面的命令以后,在项目根目录下,新建一个启动文件,假定叫做 index.js。

1
2
3
4
5
6
var express = require('express');
var app = express();

app.use(express.static(__dirname + '/public'));

app.listen(8080);

运行启动脚本
node index
访问 http://localhost:8080
它会在浏览器中打开当前目录的 public 子目录(严格来说,是打开 public 目录的 index.html 文件)。如果 public 目录之中有一个图片文件 my_image.png,那么可以用 http://localhost:8080/my_image.png 访问该文件。

目录结构
屏幕快照 2017-03-28 下午3.55.13

执行结果
屏幕快照 2017-03-28 下午3.54.14
也可以 http://localhost:8080/WX.jpeg

也可以生成动态网页

express
1
2
3
4
5
var app = express();
app.get('/', function (req, res) {
res.send('Hello world!');
});
app.listen(3000);

运行启动脚本
node index

屏幕快照 2017-03-28 下午3.57.07

启动脚本 index.js 的 app.get 方法,用于指定不同的访问路径所对应的回调函数,这叫做 “路由”(routing)。上面代码只指定了根目录的回调函数,因此只有一个路由记录。实际应用中,可能有多个路由记录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
比如:
var express = require('express');
var app = express();

app.get('/', function (req, res) {
res.send('Hello world!');
});
app.get('/customer', function(req, res){
res.send('customer page');
});
app.get('/admin', function(req, res){
res.send('admin page');
});

app.listen(3000);

比较庞大的时候可以单独存放
eg:

1
2
3
4
5
6
7
8
9
10
11
12
13
// routes/index.js

module.exports = function (app) {
app.get('/', function (req, res) {
res.send('Hello world');
});
app.get('/customer', function(req, res){
res.send('customer page');
});
app.get('/admin', function(req, res){
res.send('admin page');
});
};

原先的 index 引入

1
2
3
4
5
// index.js
var express = require('express');
var app = express();
var routes = require('./routes')(app);
app.listen(3000);

node 简介

node 是 javascript 语言的服务器运行环境
所谓的运行环境有两层意思:

  1. javascript 语言通过 node 在服务器运行,在这个意义上,node 是 javascriprt 的虚拟机
  2. node 提供大量的工具库,使得 javascript 语言与操作系统互动(比如读写文件,新建子进程),在这个意义上,node 又是 javascrip 的工具库
    Node 内部采用 Google 公司的 V8 引擎,作为 JavaScript 语言解释器;通过自行开发的 libuv 库,调用操作系统资源。

    什么是 Google V8 JavaScript 引擎

    V8 是一个由丹麦 Google 开发的开源 JavaScript 引擎,V8 就是 chrome 浏览器用的 js 解释引擎,主要是 C 编写的
    V8 在执行之前将 JavaScript 编译成了机器码,而非位元组码或是直译它,以此提升效能。更进一步,有了这些功能,JavaScript 程序与 V8 引擎的速度媲美二进制编译。[4]

    安装相关

    访问官方网站 nodejs.org
    安装完成查看 node 版本
1
2
3
$ node --version
或者
$ node -v

wunai

更新 node 版本,可以通过 node.js 的 n 模块完成,
更新为最新发布的稳定版。

1
2
$ sudo npm install n -g
$ sudo n stable

node-1-2

1
$ sudo n 0.10.21

安装版本管理工具 nvm

如果想在同一台机器同时安装多个版本的 node,就需要用到嗯本管理工具 nvm,nvm 全称 Node Version Manager,它与 n 的实现方式不同,其是通过 shell 脚本实现的。

1
2
$ git clone https://github.com/creationix/nvm.git ~/.nvm
$ source ~/.nvm/nvm.sh

node-1-3

安装最新版本
1
$ nvm install node

node-1-4

安装指定版本
1
$ nvm install 0.12.1

###### 使用已安装的最新版本

1
$ nvm use node
使用指定版本的 node
1
$ nvm use 0.12
查看本地安装的所有版本
1
$ nvm ls

node-1-5

退出已经激活的 nvm,使用 deactivate 命令。
1
$ nvm deactivate

###### 卸载 nvm

1
rm -rf ~/.nvm

###### 查看 nvm 帮助

1
nvm -h

详细文档请参考官方文档
https://github.com/creationix/nvm