Node.js 初识 HTTP 模块

简介:

一、实现“Hello World!”及相关API介绍


使用 HTTP 服务器和客户端必须使用 require('http')


Node.js 中的 HTTP 接口设计主要是为了支持 传统的很难使用的多特性的协议,尤其是大量的信息。接口没有缓冲整个接收和相应,用户可使用流式数据。


HTPP信息的头部是像一个对象那样描述的:

1
2
3
4
5
'content-length' '123' ,
   'content-type' 'text/plain' ,
   'connection' 'keep-alive' ,
   'host' 'mysite.com' ,
   'accept' '*/*'  }



http.createServer([requestListener])

Returns: <http.Server>

返回一个新的 http.Server 的实例

requestListener 是一个自动添加 'request' 的函数



server.listen([port][, hostname][, backlog][, callback])

开始接受指定的端口号(port)和主机名(hostname)之间的连接。


参数类型:

port:Number

hostname:String

backlog:Number

callback:Function


如果省略了 hostname,当IPV6可用时,服务器将连接任意的IPV6地址(::),或者是任意的IPV4地址 (0.0.0.0)

忽略 port 参数或者使用 0 作为端口号,如果想让操作系统随机分配一个端口号,可以在 'listening'

事件之后使用 server.address().port 来重新取回


如果想要监听 unix 套接字,可以用一个文件名来替换 port 和 hostname


backlog 是连接请求队列的最大长度,实际的长度将由你的 OS 通过系统调用设置来决定,比如 linux 上的 tcp_max_syn_backlog 和 somaxconn  。这个参数的默认值是511(不是512)


callback 作为 'listening' 事件的一个监听器, 是一个异步的回调函数



response.writeHead(statusCode[, statusMessage][, headers])

给请求消息发送一个响应头


statusCode  Number 类型, 是一个三位数的 HTTP 状态码 比如:404

statusMessage  String 类型,是可选的,主要是提高可读性

headers  Object 类型, 是一个响应头,第二个参数是可选的


例如:

1
2
3
var  body =  'hello world' ;response.writeHead(200, {
   'Content-Length' : Buffer.byteLength(body),
   'Content-Type' 'text/plain'  });


此方法在一个消息上只能调用一次,且必须在 response.end() 之前调用



response.end([data][, encoding][, callback])

这个方法是用来告诉服务器,所有的响应头和响应主体已经发送完毕,服务器就会知道这个消息已经完成了。每一个响应消息都必须调用 response.end()



如果指定了 data ,就相当于在 response.end(callback) 之前调用了 response.write(data, encoding)

如果指定了 callback ,将在响应流结束之后调用



结合以上内容,我们再来看一下经典的 Node.js 入门案例,在页面打印“Hello World”


基本的骨架:

1
2
3
4
5
6
7
8
9
10
//第一步: 引入 http 模块
var  http = require( 'http' );
 
//第二步:创建一个服务器(requestListener 是一个函数,里面有2个参数,一个请求消息,一个响应消息)
var  server = http.createServer( function (req, res){
 
});
 
//第三步:服务器监听本地的82端口
server.listen(8082,  '127.0.0.1' );


设置消息内容:

1
2
3
4
5
6
7
8
9
10
var  server = http.createServer( function (req, res){
     //req -> request,表示请求; res -> response,表示响应
 
     //设置响应头,第一个参数是3位数的HTTP状态码,第二个参数可选,第三个参数是一个对象,里面可存放合法的MIME类型
     //MIME类型:文件类型是纯文本,字符集编码方式是 utf8
     res.writeHead(200,{ 'Content-Type' 'text/plain; charset=utf8' });
     //响应消息发送结束,如果指定了data参数,就相当于在 res.end() 之前添加了一个 res.end(data, encoding) 方法
     //res.end('Hello World!', 'utf8');
     res.end( 'Hello World!' );
});


通过命令行工具挂起服务器,打开浏览器,在地址栏输入: 127.0.0.1:8082

wKioL1hvDxrSL8bDAAANGVtZ_-A212.png

同时,也可以打开控制台查看请求头部

wKiom1hvD_bCV6QiAADoRDifsGY587.png

值得注意的是,如果省略了 res.end(), 页面是渲染不出来的,因为服务器会一直处于等待状态,没人告诉它响应消息是否结束了



在  Node.js 三大特点详解  一文中,我们了解到传统的 HTTP服务器一般建立在 Apache、Nginx、IIS等服务器上,而 Node.js 并不需要,由于 Node.js 提供了 http 模块,自身就可以构建服务器(从上面的例子可以体会到)。


http 模块 是通过 C++实现的,性能非常可靠,其中,封装了一个 http 服务器 和一个简易的 http 客户端。http.Server 是一个基于事件的 http 服务器,http.request 则是一个 http 客户端工具,用于向 http 服务器发起请求


前面提到的 http.createServer( requestListener ) 方法中,requestListener 是一个回调函数,函数有2个参数 request 和 response,request 是 http.IncomingMessage 对象的实例,response 是  http.ServerResponse 对象的实例。下面分别来学习 HTTP 服务器 和 HTTP 客户端。



二、HTTP 服务器


先回顾下“Hello World!”这个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//第一步: 引入 http 模块
var  http = require( 'http' );
 
//第二步:创建一个服务器(requestListener 是一个函数,里面有2个参数,一个请求消息,一个响应消息)
var  server = http.createServer( function (req, res){
     //req -> request,表示请求; res -> response,表示响应
 
     //设置响应头,第一个参数是3位数的HTTP状态码,第二个参数可选,第三个参数是一个对象,里面可存放合法的MIME类型
     //MIME类型:文件类型是纯文本,字符集编码方式是 utf8
     res.writeHead(200,{ 'Content-Type' 'text/plain; charset=utf8' });
     //响应消息发送结束,如果指定了data参数,就相当于在 res.end() 之前添加了一个 res.end(data, encoding) 方法
     //res.end('Hello World!', 'utf8');
     res.end( 'Hello World!' );
});
 
//第三步:服务器监听本地的82端口
server.listen(8082,  '127.0.0.1' );


基本的结构是直接创建一个 http 对象,然后创建一个 http 对象的实例 server,并为其监听82端口


1、http.Server

http.Server 继承自 net.Server 而 net.Server是一个 EventEmitter,主要用来创建一个 TCP或者本地服务器。

事实上,Node.js 中大部分模块都继承自 EventEmitter,包括fs、net等模块,这也是为什么说 Node.js 基于事件驱动。http.Server 提供的事件如下:


request

客户端发出请求时触发,每一次连接可能会发出很多个请求(假如是持久连接的话)。提供两个参数request 和 response,是最常用的事件


connection

当 TCP 建立连接时,触发此事件,提供一个参数 socket,是 net.socket 的实例


close

当服务器关闭时,触发此事件。注意不是用户断开连接时


除此之外还有 checkContinue,upgrade,clientError 等事件,只有在实现复杂的 HTTP 服务器的时候才会用到。


在这些事件中,最常用的就是 request 事件,所以,http 提供了一个捷径:http.createServer( requestListener ),如我们所知,功能就是创建一个 HTTP 服务器并将 requestListener 作为 request 事件的监听函数,



2、http.IncomingMessage  --> request

http.IncomingMessage 是 HTTP 请求的信息,一般由 http.Server 的 request 事件发送,并作为第一个参数传递,http 请求一般包括 请求头部 和 请求主体。


其提供了三个事件用于控制请求体传输:

data: 当请求体数据到来时,触发该事件。该事件提供一个参数 chunk,表示接收到的数据。如果该事            件没有被监听,那么请求体将会被抛弃,该事件可能会被调用多次


end:当请求体数据传输完成时,该事件被触发,此后将不会再有数据到来


close:用户当前请求结束时,该事件被触发。不同于end,如果用户强制终止传输,也还是调用 close


http.IncomingMessage 的属性如下:

wKioL1hvR16BhHqmAADs9DRRqnU593.png


3、http.ServerResponse   ---> response

http.ServerResponse 是返回给客户端的信息,决定了用户最终能看到的结果。它是由 http.Server 的 request 事件发送的,作为第二个参数传递,一般简称为 response 或 res


http.ServerResponse 有三个重要的成员函数,用于返回响应头、响应内容以及结束请求(上面已经介绍过,这里再复习一次)


response.writeHead(statusCode[, statusMessage][, headers]):  向请求的客户端发送响应头

statusCode 是 HTTP状态码,常用的比如 200(请求成功),404(未找到)

headers 是一个类似关联数组的对象,表示响应头的每个属性


此函数在一个请求内最多只能调用一次,如果不调用,则会自动生成一个响应头


response.write(data, [encoding]): 向请求的客户端发送响应内容

data 是一个 Buffer 或字符串,表示要发送的内容。如果data 是字符串,那么需要指定 encoding 来说明它的编码方式,默认是 utf-8。在 response.end 调用之前,response.write 可以被多次调用


response.end([data], [encoding]): 结束响应

告知客户端所有发送已经完成,当所有要返回的内容都发送完毕的时候,该函数必须被调用一次。

此函数接受两个可选参数,意义和 response.write 相同,如果不调用此函数,客户端将用于处于等待状态(前面的案例提到过)




三、HTTP 客户端


http 模块提供了两个函数 http.request 和 http.get,功能是作为客户端向 HTTP 服务器发起请求


1、http.request(options, callback)  发起 HTTP 请求

接受两个参数,options表示请求的参数,可以是一个对象或字符串,如果是字符串的话,将自动调用      url.parse() 解析;

callback 是请求的回调函数,需要传递一个参数


options 常用的参数如下:

host:请求网站的域名或 IP 地址

port:请求网站的端口号,默认 80

method:请求方法,默认是 GET

path:请求的相对于根的路径,默认是“/”。QueryString 应该包含在其中,例如:/search?query=byvoid

headers:一个关联数组对象,为请求头的内容


http.request() 返回一个 http.ClientRequest 的实例


示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var  http=require( "http" );
 
var  options={
     hostname: "www.12306.cn" ,
     port:80
};
 
var  req=http.request(options, function (res){
     res.setEncoding( "utf-8" );
     res.on( "data" , function (chunk){
         console.log(chunk.toString())
     });
     console.log(res.statusCode);
});
req.on( "error" , function (err){
     console.log(err.message);
});
req.end();


我们运行这段代码,就可以在控制台中看到 12036 的 HTML 代码了

wKiom1hvUv3AJXl6AAD6X3woFm8991.png


2、http.get(options, callback) 

由于大多数的 GET 请求都没有主体,所以 Node.js 提供了这个简便的方法用于处理 GET 请求。

此方法是 http.request 的简化版,唯一的区别在于 http.get 自动将请求方法设为了 GET 请求,同时不需要手动调用 req.end()


1
2
3
4
5
6
7
var  http = require( 'http' );
http.get({host:  'www.12306.cn' },  function (res) {
     res.setEncoding( 'utf8' );
     res.on( 'data' function  (data) {
         console.log(data);
     });
});


运行这段代码,一样可以在控制台得到 12036 的 HTML 代码



3、http.ClientRequest

http.ClientRequest 是由 http.request 或 http.get 返回产生的对象,表示一个已经产生而且正在进行中的 HTTP 请求。

它提供了一个 response 事件,即 http.request 或 http.get,第二个参数指定的回调函数的绑定对象。我们可以显示地绑定这个事件的监听函数:


1
2
3
4
5
6
7
8
var  http = require( 'http' );
var  req = http.get({host:  'www.12306.cn' });
req.on( 'response' function (res) {
     res.setEncoding( 'utf8' );
     res.on( 'data' function  (data) {
         console.log(data);
     });
});


运行这段代码,一样可以在控制台得到 12036 的 HTML 代码


http.ClientRequest 像 http.ServerResponse 一样也提供了 write 和 end 函数,用于向服务器发送请求体,通常用于 POST、PUT 等操作。所有写结束以后必须调用 end 函数以通知服务器,否则请求无效。


http.ClientRequest 还提供了以下函数。

request.abort():终止正在发送的请求。

request.setTimeout(timeout, [callback]):设置请求超时时间,timeout 为毫秒数。当请求超时以后,callback 将会被调用。



4、http.ClientResponse


http.ClientResponse 与 http.ServerRequest 相似,提供了三个事件 data、end和 close,分别在数据到达、传输结束和连接结束时触发,其中 data 事件传递一个参数chunk,表示接收到的数据。


http.ClientResponse 也提供了一些属性,用于表示请求的结果状态

wKioL1hvV4jCIDXNAABHJxPFLr4597.png


http.ClientResponse 还提供了以下几个特殊的函数。


response.setEncoding([encoding]):设置默认的编码,当 data 事件被触发时,数据将会以 encoding 编码。默认值是 null,即不编码,以 Buffer 的形式存储。常用编码为 utf8。


response.pause():暂停接收数据和发送事件,方便实现下载功能。


response.resume():从暂停的状态中恢复。

本文转自   frwupeng517   51CTO博客,原文链接: http://blog.51cto.com/dapengtalk/1889787

相关文章
|
2月前
|
JavaScript
Node.js【GET/POST请求、http模块、路由、创建客户端、作为中间层、文件系统模块】(二)-全面详解(学习总结---从入门到深化)
Node.js【GET/POST请求、http模块、路由、创建客户端、作为中间层、文件系统模块】(二)-全面详解(学习总结---从入门到深化)
27 0
|
14天前
|
域名解析 网络协议 JavaScript
【Node系列】node工具模块
Node.js有多个内置的工具模块,这些模块提供了用于执行各种任务的功能。
22 2
|
1月前
|
JavaScript 前端开发
Node.js之path路径模块
Node.js之path路径模块
|
1月前
|
JavaScript
Node.js之http模块
Node.js之http模块
|
2月前
|
资源调度 JavaScript API
|
2月前
|
资源调度 JavaScript 关系型数据库
Node.js【文件系统模块、路径模块 、连接 MySQL、nodemon、操作 MySQL】(三)-全面详解(学习总结---从入门到深化)
Node.js【文件系统模块、路径模块 、连接 MySQL、nodemon、操作 MySQL】(三)-全面详解(学习总结---从入门到深化)
33 0
|
9月前
|
设计模式 JavaScript 前端开发
|
9月前
|
设计模式 JavaScript 前端开发
|
设计模式 JavaScript 前端开发
【javascript设计模式】2.Module(模块)模式
【javascript设计模式】2.Module(模块)模式
117 0