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);