/ node

Node.js中的HTTP服务

标签: node javaScript

Node.js最重要的功能之一就是实现HTTPHTTPS服务器的能力,对应到Node.js的具体模块为httphttps模块,但是这俩个模块实现的功能是非常的底层的,只有一些基本的处理请求或是响应的功能,而像路由、cookie、缓存等却并没有直接的方法供开发者调用。当然使用一些模块如express就能实现完整的Web服务。express这里不做过多的讨论,有兴趣的可以去官网看看介绍。express官网

URL

URL(统一资源定位符)是HTTP服务器用来处理客户端请求的一个标签,一个URL可以分为几个不同的组成部分,每一部分都为Web服务器提供了不同的信息。
一个基本的URL格式为:

protocol :// hostname[:port] / path / [?query]#fragment

从左到右依次为:协议、主机名、端口、路径名、查询/搜索条件、散列值

Node.js下的URL对象

Node.js中为了能更有效率的使用URL中的信息,提供了url模块,只需提供URL字符串就能对应的解析成为url对象。

  • url.parse(urlStr,[parseQueryString],[slashesDenotoHost])

参数列表:

  • urlStr:需要解析的URL字符串;
  • parseQueryString:一个布尔值默认为false,如果为true,那么会将查询字符串解析为对象;
  • slashesDenotoHost:一个布尔值默认为false,如果为true,则会将//host/pathURL解析为{host:'host',pathname:'/path'},而不是{pathname:'//host/path'};

下表列出了url.parse()所创建的对象的属性

|属性 | 说明|
|=== | ===|
|href | 传入的URL字符串|
|protocol | 请求协议|
|host | 主机部分包括端口|
|auth | 身份认证信息|
|hostname | 主机名|
|port | 端口号|
|pathname | 路径部分|
|search | 查询字符串|
|path | 完整路径,包括路径和搜索|
|query | 当第二参数设置为true时出现,为解析后的对象|
|hash | 散列部分信息|

当然url模块也拥有将一个url对象转换为URL字符串的能力:

  • url.farmat(urlObj);

解析URL

当资源地址有变动,并且不能修改客户端代码时,就需要将URL在服务端解析到一个新的地址。url提供了一个特定的方法来调整URL:

  • url.resolve(from,to);

栗子:

var url = require(url);
var originalUrl = 'http://host.com/resource/path?query=string#hash';
var newResource = '/another/path?querynew';
console.log(url.resolve(originalUrl,newResource));

//控制台
http://host.com/another/path?querynew

处理查询字符串&&表单参数

查询字符串和表单参数都是简单的键/值对,想要在Node.js中使用这些值,就需要使用queryString模块的parse()方法将字符串转换为JS对象。

  • queryString.parse(str,[sep],[eq],[options]);

参数列表:

  • str:需要转换的字符串;
  • sep:指定使用的分隔符,默认为&;
  • eq:指定分析师使用的赋值运算符,默认为=;
  • options:一个具有maxKey的对象,用来限制分割的数量,默认值为1000.若设置为0,则代表没有限制;

相反的同样可以将一个对象转换成为一个查询字符串:

  • queryString.stringify(obj,[sep],[eq]);

请求/响应对象

想要使用http模块,首先要了解响应和请求对象。它们提供了信息以及流入、流出HTTP客户端和服务器的许多功能。

http.ClientRequest 对象

当构建一个HTTP客户端时,通过调用http.request(),就会有一个ClientRequest对象在内部被创建。该对象表示请求的进展,使用该对象就能监控来自服务器的响应。

ClientRequest对象实现了一个Writable流,因此该对象拥有Writable的所有功能。

主要方法为:

  • http.request(options,callback);

注: callback的第一参数为一个可读流,代表服务器响应回的数据流

ClientRequest对象的简单实现:

var http = require('http');
var options = {
    hostname:'www.baidu.com',
    path:'/',
    method:'POST'
};
var req = http.request(options,function(respones){
    var str = '';
    respones.on('data',function(chunk){
        str += chunk;
    });
    response.on('end',function(){
        console.log(str);
    });
});
req.end();

创建ClientRequest对象时,options可包含的选项

选项 说明
host 请求发往的地址,默认为loaclhost
hostname host相同,但对于url.parse()的支持优于host
port 请求发往服务器的端口号。
localAddress 网络连接绑定的本地接口。
socketPath Unix域套接字。
method 指定HTTP请求方法的字符串。GETPOST等等。
path 请求资源路径的字符串。默认为'/',同时包括查询字符串。
headers 包含请求标头的对象。如:{'content-length':'750'}
auth 基本身份验证,形式为user:password
agent Agent行为的定义

ClientRequest对象提供了一些列的时间,用于触发

事件 说明
response 当从服务器接收到该请求时发出,回调将一个可读流作为第一参数
socket 当一个套接字被分配给该请求后发出
connect 每当服务器响应一个由CONNECT方法发起的请求时发出。
upgrade 当服务器响应在其标头中包含一个更新请求时发出
continue 当服务器发送一个100 Continue HTTP响应,指示客户端发送正文时发出

除了提供事件,ClientRequest对象还提供了一些写入、中止、停止请求的几种方法。

方法 说明
write(chunk,[encoding]) 把一个数据块写入请求
end([data],[encoding]) 把一个可选的数据块写入正文,然后刷新Writable流并终止该请求
abort() 中止当前请求
setTimeout(timeout,[callback]) 为请求设置套接字超时时间
setNoDelay([noDelay]) 禁用在发送数据之前的Nagle算法。
setSocketKeepAlive([enable],[initialDelay]) 启用和禁用对客户机请求的保持活动的功能

http.ServerResponse对象

HTTP服务器接收到一个request请求时,就会在内部创建一个ServerResponse对象。这个对象作为参数被传递到request事件处理程序。可使用ServerResponse对象定制并发送到客户端的响应。

ServerResponse对象实现了一个Writable流,所以它具有Writable流对象所有的功能。在处理客户端请求时,可以使用ServerResponse对象下的属性、事件和方法来建立和发送标头、写入数据,以及发送响应。下面列出了事件、属性以及方法:

事件、属性、方法 说明
close 当客户端的链接发送response.end()来完成并刷新响应之前关闭。(事件)
headersSent 布尔值:若标头已发送为true,反之为false。(属性)
sendData 布尔值:若为true,则Data的标头是自动生成的,并作为响应的一部分发送
statusCode 可以无需显示的写入标头来指定响应状态码
writeContiue() 发送一个HTTP/ 1.1 100 Continue消息给客户端,请求被发送的正文内容
writeHead(statusCode,[reasonPhrase],[header]) 把一个响应标头写入请求。具体内容见注1
setTimeout(msecs,callback) 设置客户端连接的套接字超时时间,若有一个发生超时将执行callback函数
setHeader(name,value) 设置一个特定的响应头值
getHeader(name) 获取一个已在响应中的HTTP响应头的值
removeHeader(name) 移除一个已设置的HTTP响应头
write(chunk,[encoding]) chunk(数据块)写入响应Writable中,这仅吧数据写入响应的正文部分
addTrailers(headers) HTTP尾随标头写入响应的结束处
end([data],[encoding]) 将可选的数据输出到响应正文,然后刷新Writable流并完成响应

注1: statusCodeHTTP响应状态代码,如200401500···reasonPhrase是一个字符串,表示statusCode的原因。headers为响应标头对象。如:response.writeHead(200.'Success',{'Content-Type':'text/plain'});

http.IncomingMessage 对象

无论是HTTP服务器还是HTTP客户端都会创建IncomingMessage对象。在服务端时客户端的请求由一个IncomingMessage对象表示,而在客户端时服务器响应由一个IncomingMessage对象表示。IncomingMessage对象可同时用于两者的原因在于它们的基本功能是一致的。

该对象主要实现了Readable流,表示需要接受的数据,这样就能够在需要的地方实现流读入。当然实现了Readable流意味着Readable下所有的方法和事件是具有的。但是IncomingMessage对象还单独具有了如下属性、方法、事件:

属性、方法、事件 说明
close 当底层套接字被关闭时发出(事件)
httpVersion 表示请求使用的HTTP版本(属性)
headers 表示请求包含的标头的对象
trailers 表示请求包含trailer标头的对象
method 表示请求的方法
url 发送到服务器的URL字符串。此属性只在处理客户端请求的HTTP服务器中生效
statusCode 表示来自服务器的状态码。此属性只在处理服务器响应的HTTP客户端上有效
setTimeout(msecs,callback) 设置连接的毫秒为单位的套接字超时时间。

HTTP Server对象

上述的内容主要介绍了一些在HTTP请求中的一些流对象,现在只要实现一个HTTP服务器框架就能就能够处理和响应请求了。

Node.js中的HTTP Server对象提供了HTTP的基本框架,也就是说Node.js程序就可以脱离Apache HTTP ServerIIS运行。

Server对象实现了EventEmitter提供了丰富的事件,当实现一个服务器时,至少要处理一下部分或是全部的事件:

事件 说明
request 每当服务器接收到客户端请求时触发。回调参数接受两个参数。代表的请求和响应。
connection 当一个新的TCP流建立时触发。回调函数接收套接字作为唯一的参数。
close 服务器关闭时触发。回调函数不接收参数。
checkContinue 当接收到包括期待的 100-continue 标头是触发。
connect 接收到HTTP CONNECT请求时触发。callback接收requestsockethead,它是一个包含隧道流的第一个包的缓冲区。
upgrade 当客户端请求HTTP升级是发出
clientError 当客户端连接套接字发出一个错误是发出

要启动HTTP服务器,首先要使用createServer()方法创建一个Server对象,

  • http.createServer([requestListener]);

此方法返回Server对象,可选的requestListener参数是在请求事件被触发时执行的回调函数。参数列表和request事件相同。第一个参数表示客户端请求的IncomingMessage对象,第二个对象是用来制定和发送响应的ServerResponse对象。

创建了Server对象,就可以通过调用Server对象上的listen()方法开始监听:

  • listen(port,[hostname],[backlog],[callback]);

参数列表:

  • port:表示监听的端口;
  • hostname:主机名称;
  • backlog:指定被允许进行排队的最大待处理连接数;
  • callback:指定服务器开始在指定的端口上监听时,要执行的回调处理程序。

大致的结构长这样:

var http = require('http');
http.createServer(function(req,res){
    //处理程序代码
}).listen(8080);