node.js学习(HTTP)
2014-12-13 14:18
190 查看
API走马观花
我们先大致看看NodeJS提供了哪些和网络操作有关的API。这里并不逐一介绍每个API的使用方法,官方文档已经做得很好了。
HTTP
官方文档: http://nodejs.org/api/http.html'http'模块提供两种使用方式:
作为服务端使用时,创建一个HTTP服务器,监听HTTP客户端请求并返回响应。
作为客户端使用时,发起一个HTTP客户端请求,获取服务端响应。
首先我们来看看服务端模式下如何工作。如开门红中的例子所示,首先需要使用
.createServer方法创建一个服务器,然后调用
.listen方法监听端口。之后,每当来了一个客户端请求,创建服务器时传入的回调函数就被调用一次。可以看出,这是一种事件机制。
HTTP请求本质上是一个数据流,由请求头(headers)和请求体(body)组成。例如以下是一个完整的HTTP请求数据内容。
?
http模块创建的HTTP服务器在接收到完整的请求头后,就会调用回调函数。在回调函数中,除了可以使用
request对象访问请求头数据外,还能把
request对象当作一个只读数据流来访问请求体数据。以下是一个例子。
?
?
response对象来写入响应头数据外,还能把
response对象当作一个只写数据流来写入响应体数据。例如在以下例子中,服务端原样将客户端请求的请求体数据返回给客户端。
?
?
.request方法创建了一个客户端,并指定请求目标和请求头数据。之后,就可以把
request对象当作一个只写数据流来写入请求体数据和结束请求。另外,由于HTTP请求中
GET请求是最常见的一种,并且不需要请求体,因此
http模块也提供了以下便捷API。
?
response对象访问响应头数据外,还能把
response对象当作一个只读数据流来访问响应体数据。以下是一个例子。
?
HTTPS
官方文档: http://nodejs.org/api/https.htmlhttps模块与
http模块极为类似,区别在于
https模块需要额外处理SSL证书。
在服务端模式下,创建一个HTTPS服务器的示例如下。
?
options对象,通过
key和
cert字段指定了HTTPS服务器使用的私钥和公钥。
另外,NodeJS支持SNI技术,可以根据HTTPS客户端请求使用的域名动态使用不同的证书,因此同一个HTTPS服务器可以使用多个域名提供服务。接着上例,可以使用以下方法为HTTPS服务器添加多组证书。
?
http模块几乎相同,示例如下。
?
https模块会拒绝连接,提示说有证书安全问题。在
options里加入
rejectUnauthorized: false字段可以禁用对证书有效性的检查,从而允许
https模块请求开发环境下使用***证书的HTTPS服务器。
URL
官方文档: http://nodejs.org/api/url.html处理HTTP请求时
url模块使用率超高,因为该模块允许解析URL、生成URL,以及拼接URL。首先我们来看看一个完整的URL的各组成部分。
?
.parse方法来将一个URL字符串转换为URL对象,示例如下。
?
.parse方法的不一定要是一个完整的URL,例如在HTTP服务器回调函数中,
request.url不包含协议头和域名,但同样可以用
.parse方法解析。
?
.parse方法还支持第二个和第三个布尔类型可选参数。第二个参数等于
true时,该方法返回的URL对象中,
query字段不再是一个字符串,而是一个经过
querystring模块转换后的参数对象。第三个参数等于
true时,该方法可以正确解析不带协议头的URL,例如
//www.example.com/foo/bar。
反过来,
format方法允许将一个URL对象转换为URL字符串,示例如下。
?
.resolve方法可以用于拼接URL,示例如下。
?
Query String
官方文档: http://nodejs.org/api/querystring.htmlquerystring模块用于实现URL参数字符串与参数对象的互相转换,示例如下。
?
Zlib
官方文档: http://nodejs.org/api/zlib.htmlzlib模块提供了数据压缩和解压的功能。当我们处理HTTP请求和响应时,可能需要用到这个模块。
首先我们看一个使用
zlib模块压缩HTTP响应体数据的例子。这个例子中,判断了客户端是否支持gzip,并在支持的情况下使用
zlib模块返回gzip之后的响应体数据。
?
zlib模块解压HTTP响应体数据的例子。这个例子中,判断了服务端响应是否使用gzip压缩,并在压缩的情况下使用
zlib模块解压响应体数据。
?
Net
官方文档: http://nodejs.org/api/net.htmlnet模块可用于创建Socket服务器或Socket客户端。由于Socket在前端领域的使用范围还不是很广,这里先不涉及到WebSocket的介绍,仅仅简单演示一下如何从Socket层面来实现HTTP请求和响应。
首先我们来看一个使用Socket搭建一个很不严谨的HTTP服务器的例子。这个HTTP服务器不管收到啥请求,都固定返回相同的响应。
?
data事件监听函数来获取服务器响应。
?
灵机一点
使用NodeJS操作网络,特别是操作HTTP请求和响应时会遇到一些惊喜,这里对一些常见问题做解答。问: 为什么通过
headers对象访问到的HTTP请求头或响应头字段不是驼峰的?
答: 从规范上讲,HTTP请求头和响应头字段都应该是驼峰的。但现实是残酷的,不是每个HTTP服务端或客户端程序都严格遵循规范,所以NodeJS在处理从别的客户端或服务端收到的头字段时,都统一地转换为了小写字母格式,以便开发者能使用统一的方式来访问头字段,例如
headers['content-length']。
问: 为什么
http模块创建的HTTP服务器返回的响应是
chunked传输方式的?
答: 因为默认情况下,使用
.writeHead方法写入响应头后,允许使用
.write方法写入任意长度的响应体数据,并使用
.end方法结束一个响应。由于响应体数据长度不确定,因此NodeJS自动在响应头里添加了
Transfer-Encoding: chunked字段,并采用
chunked传输方式。但是当响应体数据长度确定时,可使用
.writeHead方法在响应头里加上
Content-Length字段,这样做之后NodeJS就不会自动添加
Transfer-Encoding字段和使用
chunked传输方式。
问: 为什么使用
http模块发起HTTP客户端请求时,有时候会发生
socket hang up错误?
答: 发起客户端HTTP请求前需要先创建一个客户端。
http模块提供了一个全局客户端
http.globalAgent,可以让我们使用
.request或
.get方法时不用手动创建客户端。但是全局客户端默认只允许5个并发Socket连接,当某一个时刻HTTP客户端请求创建过多,超过这个数字时,就会发生
socket hang up错误。解决方法也很简单,通过
http.globalAgent.maxSockets属性把这个数字改大些即可。另外,
https模块遇到这个问题时也一样通过
https.globalAgent.maxSockets属性来处理。
小结
本章介绍了使用NodeJS操作网络时需要的API以及一些坑回避技巧,总结起来有以下几点:http和
https模块支持服务端模式和客户端模式两种使用方式。
request和
response对象除了用于读写头数据外,都可以当作数据流来操作。
url.parse方法加上
request.url属性是处理HTTP请求时的固定搭配。
使用
zlib模块可以减少使用HTTP协议时的数据传输量。
通过
net模块的Socket服务器与客户端可对HTTP协议做底层操作。
小心踩坑。
相关文章推荐
- 从零开始学习Node.js例子九 设置HTTP头
- Node.js学习——HTTP
- Node.js学习笔记(4)——除了HTTP(服务器和客户端)部分
- node.js学习笔记——学生信息管理的实现(把功能模块化)使用官方提供的http模块实现
- node.js 基础学习笔记3 -http
- Node.js学习教程之HTTP/2服务器推送【译】
- 从零开始学习Node.js系列教程之设置HTTP头的方法示例
- 从零开始学习Node.js例子一 http get和post
- 从零开始学习Node.js例子七 发送HTTP客户端请求并显示响应结果
- node.js学习笔记之HTTP---发送服务器端响应流
- node.js学习笔记之HTTP客户端
- node.js学习笔记之HTTP获取客户端请求信息
- 从零开始学习Node.js系列教程一:http get和post用法分析
- Node.js学习--基础知识(9)--HTTP客户端
- 从零开始学习Node.js例子七 发送HTTP客户端请求并显示响应结果
- Node.js学习笔记(3、http模块)
- node.js模块学习(三) http
- node.js+android(使用HttpURLConnection和HttpClient)实现文件上传
- golang与node.js的http对比测试
- node.js+android http请求响应