咱们知道传统的HTPP服务器会由Aphche、Nginx、IIS之类的软件来担任,可是nodejs并不须要,nodejs提供了http模块,自身就能够用来构建服务器,并且http模块是由C++实现的,性能可靠。咱们在nodejs中的教程或者书籍中经常会经过一个简易的http服务器来做为开头的学习,就像下面这个例子javascript
var http=require("http"); http.createServer(function(req,res){ res.writeHead(200,{ "content-type":"text/plain" }); res.write("hello nodejs"); res.end(); }).listen(3000);
打开浏览器,输入localhost:3000咱们就能够看到屏幕上的hello nodejs了,这代表这个最简单的nodejs服务器已经搭建成功了。
nodejs中的http模块中封装了一个HTPP服务器和一个简易的HTTP客户端,http.Server是一个基于事件的http服务器,http.request则是一个http客户端工具,用于向http服务器发起请求。而上面的createServer方法中的参数函数中的两个参数req和res则是分别表明了请求对象和响应对象。其中req是http.IncomingMessage的实例,res是http.ServerResponse的实例,这能够从nodejs中的源码中获取这个信息(固然咱们做为初学者,天然是不太可能读懂其源码,推荐慕课网的课程《进击的nodjs基础(一)》,scott老师会带咱们基本走一下http模块的源码,会有一个大概的了解)。如下将从http服务器和http客户端简要走一遍http模块html
文章开头使用的createServer方法返回了一个http.Server对象,这实际上是一个建立http服务的捷径,若是咱们用如下代码来实现的话,也将同样可行java
var http=require("http"); var server=new http.Server(); server.on("request",function(req,res){ res.writeHead(200,{ "content-type":"text/plain" }); res.write("hello nodejs"); res.end(); }); server.listen(3000);
以上代码是经过直接建立一个http.Server对象,而后为其添加request事件监听,其实也就说createServer方法其实本质上也是为http.Server对象添加了一个request事件监听,这彷佛更好理解了,那让咱们看看http.Server的事件吧node
正如咱们上面所说,http.Server是一个基于事件的服务器,她是继承自EventEmitter,事实上,nodejs中大部分模块都继承自EventEmitter,包括fs、net等模块,这也是为何说nodejs基于事件驱动(关于EventEmitter的更多内容能够在官方api下的events模块找到),http.Server提供的事件以下:jquery
正如上面咱们所看到的request事件是最经常使用的,而参数req和res分别是http.IncomingMessage和http.ServerResponse的实例,那么咱们来看看这两个类吧json
http.IncomingMessage是HTTP请求的信息,是后端开发者最关注的内容,通常由http.Server的request事件发送,并做为第一个参数传递,http请求通常能够分为两部分:请求头和请求体(更多关于http协议的知识能够查看我以前的笔记http入门与挖坑);其提供了3个事件,以下后端
http.IncomingMessage的属性以下:api
http.ServerResponse是返回给客户端的信息,决定了用户最终看到的内容,通常也由http.Server的request事件发送,并做为第二个参数传递,它有三个重要的成员函数,用于返回响应头、响应内容以及结束请求数组
看完http服务器,咱们看一看http的客户端吧浏览器
http模块提供了两个函数http.request和http.get,功能是做为客户端向http服务器发起请求。
options是一个相似关联数组的对象,表示请求的参数,callback做为回调函数,须要传递一个参数,为http.ClientResponse的实例,http.request返回一个http.ClientRequest的实例。
options经常使用的参数有host、port(默认为80)、method(默认为GET)、path(请求的相对于根的路径,默认是“/”,其中querystring应该包含在其中,例如/search?query=byvoid)、headers(请求头内容)
以下示例代码:
var http=require("http"); var options={ hostname:"cn.bing.com", 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();
咱们运行这段代码咱们在控制台能够发现,必应首页的html代码已经呈现出来了。
接下来咱们来作一个关于POST请求的代码。
var http=require("http"); var querystring=require("querystring"); var postData=querystring.stringify({ "content":"我真的只是测试一下", "mid":8837 }); var options={ hostname:"www.imooc.com", port:80, path:"/course/document", method:"POST", headers:{ "Accept":"application/json, text/javascript, */*; q=0.01", "Accept-Encoding":"gzip, deflate", "Accept-Language":"zh-CN,zh;q=0.8", "Connection":"keep-alive", "Content-Length":postData.length, "Content-Type":"application/x-www-form-urlencoded; charset=UTF-8", "Cookie":"imooc_uuid=6cc9e8d5-424a-4861-9f7d-9cbcfbe4c6ae; imooc_isnew_ct=1460873157; loginstate=1; apsid=IzZDJiMGU0OTMyNTE0ZGFhZDAzZDNhZTAyZDg2ZmQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjkyOTk0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGNmNmFhMmVhMTYwNzRmMjczNjdmZWUyNDg1ZTZkMGM1BwhXVwcIV1c%3DMD; PHPSESSID=thh4bfrl1t7qre9tr56m32tbv0; Hm_lvt_f0cfcccd7b1393990c78efdeebff3968=1467635471,1467653719,1467654690,1467654957; Hm_lpvt_f0cfcccd7b1393990c78efdeebff3968=1467655022; imooc_isnew=2; cvde=577a9e57ce250-34", "Host":"www.imooc.com", "Origin":"http://www.imooc.com", "Referer":"http://www.imooc.com/video/8837", "User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2763.0 Safari/537.36", "X-Requested-With":"XMLHttpRequest", } } var req=http.request(options,function(res){ res.on("data",function(chunk){ console.log(chunk); }); res.on("end",function(){ console.log("评论完毕!"); }); console.log(res.statusCode); }); req.on("error",function(err){ console.log(err.message); }) req.write(postData); req.end();
这段代码咱们模拟了向慕课网发起评论的功能,可是由于慕课网对于这种发起方式专门作了重定向,因此咱们并不能在评论区看到咱们的评论(另外在一些对这种请求没有作处理的网站,擅自发起评论,极可能会当作网络攻击,因此不要玩火,你懂得),可是这段代码却很能够说明这个过程。另外,代码中的请求头和postData里面的键咱们都是能够经过开发者工具network下找到的。
这个方法是http.request方法的简化版,惟一的区别是http.get自动将请求方法设为了GET请求,同时不须要手动调用req.end(),可是须要记住的是,若是咱们使用http.request方法时没有调用end方法,服务器将不会收到信息。由于http.get和http.request方法都是放回一个http.ClientRequest对象,因此咱们来看一下这两个对象。
http.ClientRequest是由http.request或者是http.get返回产生的对象,表示一个已经产生并且正在进行中的HTPP请求,提供一个response事件,也就是咱们使用http.get和http.request方法中的回调函数所绑定的对象,咱们能够显式地绑定这个事件的监听函数
var http=require("http"); var options={ hostname:"cn.bing.com", port:80 } var req=http.request(options); req.on("response",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();
http.ClientRequest也提供了write和end函数,用于向服务器发送请求体,一般用于POST、PUT等操做,全部写操做都必须调用end函数来通知服务器,不然请求无效。此外,这个对象还提供了abort()、setTimeout()等方法,具体能够参考文档
与http.ServerRequest类似,提供了三个事件,data、end、close,分别在数据到达、传输结束和链接结束时触发,其中data事件传递一个参数chunk,表示接受到的数据。其属性以下
此外,这个对象提供了几个特殊的函数
好的,到这里http模块的主要功能已经介绍完了。咱们接着来作一个练习,咱们知道中山大学今年院系改革,弄得我这个中大学生也不知道中大到底有那些学院了,是的,咱们打开官网咱们会发现有哪些学院,可是我想用http模块把里面的学院名给扒下来,好的,那我就作了如下代码
var cheerio=require("cheerio"); var http=require("http"); var fs=require("fs"); var options="http://www.sysu.edu.cn/2012/cn/jgsz/yx/index.htm"; var htmlData="" var req=http.request(options,function(res){ res.on("data",function(chunk){ htmlData+=chunk; }); res.on("end",function(){ var $=cheerio.load(htmlData); var textcontent=$("tr").text(); fs.writeFile("./school.txt",textcontent,"utf-8") }); }); req.end();
以后咱们就可在school.txt文件中看到全部的学院了,怎么样,是否是颇有成就感,题外话,我这里用了一个外部的模块cheerio,这个模块可让咱们像jquery同样操做html代码,这个模块的介绍就到这里了(你们不要用这个模块的知识去干坏事哦,不然我可不负责┑( ̄Д  ̄)┍)。