使用nodejs实现静态服务器与用到的方法

添加node内置模块,通过require加载:

var http = require('http')
var path = require('path')
var fs = require('fs')
var url = require('url')

整个底层服务器是由node提供的http模块实现的。

创建server

http.server是一个基于事件的HTTP服务器,所有的请求都被封装到独立的事件当中。

http.createServer(function(req, res){
    res.setHeader('Content-Type','text/html; charset=utf-8')
    res.writeHead(200, 'ok')
    res.write('hello world')
    res.end()
})

两个参数request和response,分别是http.ServerRequest和http.ServerResponse表示请求和响应的信息。

http.ServerResponse返回客户端信息

决定了用户最终能到的结果,它是由http.Server的request事件发送的,作为第二个参数传递,一般用response或res表示。
主要的三个函数:

  • response.writeHead(statusCode, [headers]):向请求的客户端发送响应头。statusCode是HTTP的状态码,如200为成功,404未找到等。headers是一个类似关联数组的对象,表示响应头的每个属性。
  • response.write(data, [encoding]):向请求客户端发送相应内容,data是buffer或字符串,encoding为编码。
  • response.end([data], [encoding]):结束响应,告知用户所有发送已经完成,当所有要返回的内容发送完毕,该函数必须被调用一次,如果不调用,客户端永远处于等待状态

http.ServerRequset请求信息

HTTP请求分为两部分请求头请求体,如果请求内容少直接在请求头协议完成之后立即读取,请求体相对较长,需要一定的时间传输,因此提供了三个事件用于控制请求体传输:
data:当请求体数据到来时,该事件被触发,有一个参数chunk,表示接受到的数据。
end:当请求体数据传输完成时,该事件被触发,此后将不会再有数据到来。
close:用户当前请求结束时,该事件被触发,不同于end,如果用户强制终止了传输,也会触发close。
ServerRequset的属性:

名称 含义
complete 客户端请求是否已经发送完成
httpVersion HTTP协议版本,通常是1.0或1.1
method HTTP请求方法,如GET、POST
url 原始的请求路径
headers HTTP请求头
trailers HTTP请求尾(不常见)
connection 当前HTTP连接套接字,为net.Socket的实例
socket connection属性的别名
client client属性的别名

获取GET请求内容

由于GET请求直接被嵌入在路径中,URL是完整的请求路径,包括了?后面的部分,因此可以手动解析后面的内容作为GET请求的参数。
node.js中url模块中的parse函数提供了这个功能。
参考:Node.js GET/POST请求

var http = require('http');
var url = require('url');
var util = require('util');
 
http.createServer(function(req, res){
    res.writeHead(200, {'Content-Type': 'text/plain; charset=utf-8'});
    //利用url模块去解析客户端发送过来的Url对象
    res.end(util.inspect(url.parse(req.url, true)));
}).listen(8080);

注:util.inspect
util.inspect(object, [showHidden], [depth], [colors])是一个将任意对象转换为字符串的方法,通常用于调试和错误输出。它至少接受一个参数object,即要转换的对象。
showHidden:是一个可选参数,如果值为true,将会输出更多隐藏信息。
depth:表示最大递归的层数,如果对象很复杂,可以指定层数以控制输出信息的多少。如果不指定depth,默认会递归2层,指定为null表示将不限递归层数完整遍历对象。
color:如果值为true,输出格式将会以ANSI颜色编码,通常用于在终端显示更漂亮的效果。
特别要指出的是,util.inspect并不会简单地直接把对象转换为字符串,即使该对象定义了toString方法也不会调用。
参考:Node.js常用工具

var util = require('util'); 
function Person() { 
    this.name = 'byvoid'; 
    this.toString = function() { 
    return this.name; 
    }; 
} 
var obj = new Person(); 
console.log(util.inspect(obj)); 
console.log(util.inspect(obj, true));

输出结果:

Person { name: 'byvoid', toString: [Function] }
Person {
  name: 'byvoid',
  toString: 
   { [Function]
     [length]: 0,
     [name]: '',
     [arguments]: null,
     [caller]: null,
     [prototype]: { [constructor]: [Circular] } } }

获取POST请求内容

POST 请求的内容全部的都在请求体中,http.ServerRequest 并没有一个属性内容为请求体,原因是等待请求体传输可能是一件耗时的工作。
比如上传文件,而很多时候可能并不需要理会请求体的内容,恶意的POST请求会大大消耗服务器的资源,所以node.js默认是不会解析请求体的,当需要时要手动来做。
参考:Node.js GET/POST请求
基本语法结构:

var http = require('http');
var querystring = require('querystring');
http.createServer(function(req, res){
    // 定义了一个post变量,用于暂存请求体的信息
    var post = '';     
    // 通过req的data事件监听函数,每当接受到请求体的数据,就累加到post变量中
    req.on('data', function(chunk){    
        post += chunk;
    });
    // 在end事件触发后,通过querystring.parse将post解析为真正的POST请求格式,然后向客户端返回。
    req.on('end', function(){    
        post = querystring.parse(post);
        res.end(util.inspect(post));
    });
}).listen(8080);

举例:表单通过 POST 提交并输出数据

var http = require('http');
var querystring = require('querystring');
 
var postHTML = 
  '菜鸟教程 Node.js 实例' +
  '' +
  '
' + '网站名:
' + '网站 URL:
' + '' + '
' + ''; http.createServer(function (req, res) { var body = ""; req.on('data', function (chunk) { body += chunk; }); req.on('end', function () { // 解析参数 body = querystring.parse(body); // 设置响应头部信息及编码 res.writeHead(200, {'Content-Type': 'text/html; charset=utf8'}); if(body.name && body.url) { // 输出提交的数据 res.write("网站名:" + body.name); res.write("
"); res.write("网站 URL:" + body.url); } else { // 输出表单 res.write(postHTML); } res.end(); }); }).listen(3000);

访问‘localhost:3000’,在input表单中分别输入‘饥人谷’ ‘jirengu.com’,点提交,输出:

网站名:饥人谷
网站 URL:jirengu.com

__dirname和__filename

__dirname等同于path.dirname(__filename)
__dirname返回当前模块文件解析过后所在的文件夹(目录)的绝对路径;
__filename返回当前模块文件被解析过后的绝对路径。

使用nodejs实现静态服务器与用到的方法_第1张图片

举例,在index.js中:

console.log('这是staticPath:'+ staticPath)
console.log('这是req.url:'+ req.url)
console.log('这是__dirname:' + __dirname)
console.log('这是__filename:' + __filename)
console.log('这是path.dirname(__filename):' + path.dirname(__filename))
//输出
这是staticPath:/Users/WRX/projects/Demo/node-server/sample
这是req.url:/getWeather?city=beijing
这是__dirname:/Users/WRX/projects/Demo/node-server
这是__filename:/Users/WRX/projects/Demo/node-server/index.js
这是path.dirname(__filename):/Users/WRX/projects/Demo/node-server

fs.readFileSync方法

fs.readFileSync(filename, [encoding])
由于该方法属于fs模块,使用前需要引入fs模块(var fs = require('fs'))
接受参数:
filename:文件路径
options:option对象,包含encoding,编码格式,该项是可选的。
举例:

var fs = require('fs')
var contentText = fs.readFileSync('123.txt','utf-8')
console.log(contentText);

在index-simple.js中,文件路径filename为:__dirname + '/sample' + req.url,拼装成完整的路径。

try与catch的使用

try{
    //代码区
}catch(Exception e){
    //异常处理
}

代码区如果有错误,就会返回所写异常的处理。(如果没有try,出现异常会导致程序崩溃,而try则可以保证程序的正常运行。)
try catch是捕捉try部分的异常,当没有try时,如果出现异常程序报错,加上try catch,出现异常程序正常运行,只是把错误信息存储到Exception里,所以catch是用来提取异常信息的,可以在catch部分加System.out.println(e.ToString());,如果出现异常可以把异常打印出来。

println和print基本没什么差别,就是最后会换行。
print将它的参数显示在命令窗口,并将输出光标定位在所显示的最后一个字符之后。
println将它的参数显示在命令窗口,并在结尾加上换行符,将输出光标定位在下一行的开始。

url.parse(req.url,true)

将一个url字符串转换成对象并返回,使用前需要引入url(var url = require('url'))
url.parse(urlStr, [parseQueryString], [slashesDenoteHost]),默认情况url.parse(url)等价于url.parse(url, false, false)
接受参数:
urlStr:url字符串;
parseQueryString:控制解析的 Url {……} 中的query字段的值是否为JSON格式,即{……},还是普通字符串格式,即‘……’,默认false为字符串格式;
slashesDenoteHost:默认为false,//foo/bar形式的字符串将被解释成{pathname: ‘//foo/bar’};如果为true,//foo/bar形式的字符串将被解释成{host: ‘foo',pathname: ‘/bar'}。
举例:

var url = require('url');
var a = url.parse('http://localhost:8080/one?a=index&t=article');
console.log(a);
Url { 
    protocol : 'http' ,
    auth : null ,
    host : 'localhost:8080' ,
    port : '8080' ,
    hostname : 'localhost' ,
    hash : null ,
    search : '?a=index&t=article',
    query : 'a=index&t=article',
    pathname : '/one',
    path : '/one?a=index&t=article',
    href : 'http://localhost:8080/one?a=index&t=article'
}

你可能感兴趣的:(使用nodejs实现静态服务器与用到的方法)