终极目标:掌握和使用node

本博客目的:记录node学习的进度和心得

内容:Nodejs中的利用HTTP模块 URl模块 PATH模块 FS模块创建一个WEB服务器。

WEB服务器

​ Web服务器一般指网站服务器,是指驻留于因特网上某种类型计算机的程序,可以向浏览器等Web客户端提供文档,也可以放置网站文件,让全世界浏览;可以放置数据文件,让全世界下载。

​ 目前最主流的三个Web服务器是Apache Nginx IIS。

Nodejs创建一个WEB服务器

​ 可以用nodejs提供一个WEB服务器。

​ 最初,我们会放置静态文件到服务器,有图片,css,JS,HTML等。然后当客户端发送请求,服务器需要解析请求URL,找到正确的资源位置,然后以一定形式返回。

image-20200514145758710

​ 例子1:

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//引入http模块
var http=require('http');

//fs模块

var fs=require('fs');
http.createServer(function(req,res){

//http://localhost:8001/news.html /news.html
//http://localhost:8001/index.html /index.html

//css/dmb.bottom.css

var pathname=req.url;
if(pathname=='/'){//为路径URL为空
pathname='/index.html'; /*默认加载的首页*/
}

if(pathname!='/favicon.ico'){ /*过滤请求favicon.ico图片文件*/
console.log(pathname);
//文件操作获取 static下面的index.html
//读取文件
fs.readFile('static/'+pathname,function(err,data){

if(err){ /*没有这个文件*/

console.log('404');

}else{ /*返回这个文件*/
//写入响应头
res.writeHead(200,{"Content-Type":"text/html;charset='utf-8'"});
res.write(data);
res.end(); /*结束响应*/
}


})


}

}).listen(8001);//设置监听端口号

在VSCODE运行这段代码,然后打开浏览器,对应URL即可完成本地服务器对文件或网页的访问。

image-20200514150441598

但我们从F12浏览器控制台发现,我们请求这个index.html文件的时候,这个HTML加载请求了很多CSS文件和JS文件,但发现其并没有加载在页面上展示。

image-20200514150913766

原因在于:当我们CSS文件的响应头,发现其是content type是text/html,内容解析为text/html。所以我们应该在源代码上对不同的文件,修改对应不同的响应头。

image-20200514150801400

例子2:

如果页面404,可以转入到自定义显示404的404.html文件上。

根据不同后缀名,返回不同的content type的响应头。这里,除了可以使用原生JS,通常使用node内置的path模块。(例如后缀名就是path.extname(“XXX.CSS”))

我们可以先定义一个后缀名处理的模块。

image-20200514152125341

在代码引入之前后缀名处理模块,和修改相关代码:

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

//引入http模块
var http=require('http');

//fs模块

var fs=require('fs');

//path模块
var path=require('path'); /*nodejs自带的模块*/


var mimeModel=require('./model/getmime.js');

//console.log(mime.getMime('.css')); //获取文件类型

http.createServer(function(req,res){



//http://localhost:8001/news.html /news.html
//http://localhost:8001/index.html /index.html

//css/dmb.bottom.css

var pathname=req.url;
if(pathname=='/'){
pathname='/index.html'; /*默认加载的首页*/
}

//获取文件的后缀名
var extname=path.extname(pathname);

if(pathname!='/favicon.ico'){ /*过滤请求favicon.ico*/
//console.log(pathname);
//文件操作获取 static下面的index.html

fs.readFile('static/'+pathname,function(err,data){

if(err){ /*么有这个文件*/

console.log('404');

fs.readFile('static/404.html',function(error,data404){
if(error){
console.log(error);
}
res.writeHead(404,{"Content-Type":"text/html;charset='utf-8'"});
res.write(data404);
res.end(); /*结束响应*/
})

}else{ /*返回这个文件*/

var mime=mimeModel.getMime(extname); /*获取文件类型*/
res.writeHead(200,{"Content-Type":""+mime+";charset='utf-8'"});
res.write(data);
res.end(); /*结束响应*/
}


})


}

}).listen(8001);


然后运行。

此时,CSS,js文件都正确加载了:

image-20200514152417602

因为不同文件的响应头写正确了:

image-20200514152601508

但仍然存在一些问题:

image-20200514152943500

我们之前使用的是var pathname=req.url;

image-20200514153403106

image-20200514153519946

所以,一些JSON的get传值没有找到,这个时候需要使用URL模块及其相关方法,正确找到pathname。

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

//引入http模块
var http=require('http');

//fs模块

var fs=require('fs');

//path模块
var path=require('path'); /*nodejs自带的模块*/

//url模块

var url=require('url');


var mimeModel=require('./model/getmime.js');

//console.log(mime.getMime('.css')); //获取文件类型

http.createServer(function(req,res){



//http://localhost:8001/news.html /news.html
//http://localhost:8001/index.html /index.html

//css/dmb.bottom.css

var pathname=url.parse(req.url).pathname;//这样就会把url转成一个对象,然后取pathname属性

console.log(pathname);

if(pathname=='/'){
pathname='/index.html'; /*默认加载的首页*/
}

//获取文件的后缀名
var extname=path.extname(pathname);

if(pathname!='/favicon.ico'){ /*过滤请求favicon.ico*/
//console.log(pathname);
//文件操作获取 static下面的index.html

fs.readFile('static/'+pathname,function(err,data){

if(err){ /*么有这个文件*/

console.log('404');

fs.readFile('static/404.html',function(error,data404){
if(error){
console.log(error);
}
res.writeHead(404,{"Content-Type":"text/html;charset='utf-8'"});
res.write(data404);
res.end(); /*结束响应*/
})

}else{ /*返回这个文件*/

var mime=mimeModel.getMime(extname); /*获取文件类型*/
res.writeHead(200,{"Content-Type":""+mime+";charset='utf-8'"});
res.write(data);
res.end(); /*结束响应*/
}


})


}



}).listen(8001);

此时,一些JSON数据也正确加载往网页了:

image-20200514153656501

JSON文件也响应成功:

image-20200514153723185

小结:这样就完成了一个最基本的静态服务器功能。

但是,仍然存在一些问题:

例如图片文件,响应头返回text/html:

image-20200514154003864

实际上,我们会写一个image-20200514154033576

控制所有文件格式对应的content type:

image-20200514154104977

类似地,重新写一个读取后缀名的方法模块:

注意如果使用fs.readFile是一个异步读取文件的方式,可能导致请求时读取不到数据,显示undefined。

所以应该使用同步的方法fs.readFileSync:

image-20200514155222272

然后在使用的地方引入使用:

image-20200514155318278

最后就可以得到CSS(任意文件)对应的content type(text/css)。

因此,最后只需在源代码基础上修改获取扩展名方法的模块及对应方法:

image-20200514160106605

运行

image-20200514160217950

此时,对应文件的content type正确按照我们JSON文件对应上了。

小结:这样就使用nodejs创建了一个类似Apache Nginx IIS的WEB服务器。

最后的完整代码:

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

//引入http模块
var http=require('http');

//fs模块

var fs=require('fs');

//path模块
var path=require('path'); /*nodejs自带的模块*/

//url模块

var url=require('url');

//引入扩展名的方法是在文件里面获取到的。

var mimeModel=require('./model/getmimefromfile.js');

//console.log(mimeModel.getMime('.css')); //获取文件类型

http.createServer(function(req,res){



//http://localhost:8001/news.html /news.html
//http://localhost:8001/index.html /index.html

//css/dmb.bottom.css

//xxx.json?214214124

var pathname=url.parse(req.url).pathname;

console.log(pathname);

if(pathname=='/'){
pathname='/index.html'; /*默认加载的首页*/
}

//获取文件的后缀名
var extname=path.extname(pathname);

if(pathname!='/favicon.ico'){ /*过滤请求favicon.ico*/
//console.log(pathname);
//文件操作获取 static下面的index.html

fs.readFile('static/'+pathname,function(err,data){

if(err){ /*么有这个文件*/

console.log('404');

fs.readFile('static/404.html',function(error,data404){
if(error){
console.log(error);
}
res.writeHead(404,{"Content-Type":"text/html;charset='utf-8'"});
res.write(data404);
res.end(); /*结束响应*/
})

}else{ /*返回这个文件*/

var mime=mimeModel.getMime(fs,extname); /*获取文件类型*/
res.writeHead(200,{"Content-Type":""+mime+";charset='utf-8'"});
res.write(data);
res.end(); /*结束响应*/
}
})

}

}).listen(8002);