深入解析nodejs HTTP服务
我最近在研究nodejs的路上,正好这两天了解了nodejs http服务,那么今天也算个学习笔记吧!
nodejs最重要的方面之一是具有非常迅速的实现http和https服务器和服务的能力。http服务是相当低层次的,你可能要用到不同的模块,如express来实现完整的web服务器,http模块不提供处理路由、cookie、缓存等的调用。我们主要用http模块的地方是实现供应用程序使用的后端web服务。
1.处理url
统一资源定位符(url)为把一个请求发到正确的服务器的特定端口上,并访问合适的数据提供了所有需要的信息。一个url可以被分解成几个不同的组成部分,每个部分都为web服务器如何路由和处理来自客户端的http请求提供一块基本的信息。node提供了url模块,提供了把一个url字符串转换成一个url对象的功能。
要从一个url字符串创建url对象,把url字符串作为第一个参数下面的方法:
url.parse(urlstr,[parsequerystring],[slashesdenotehost)
其中,parsequerystring参数是一个布尔值,如果为true,那么也把url的查询字符串部分解析为对象字面量,默认值为false。
slashesdenotehost参数也是一个布尔值,如果为true,那么就会把格式为//host/path的url解析为{host:'host',pathname:'/path'},而不是{pathname:'//host/path'}
还可以用url.format(urlobj)方法将一个url对象转换成字符串的形式。
由url.parse()创建出来的url对象的属性:
- path 完整路径,包括路径和搜索
- query 要么是查询字符串中的参数部分,要么是含有查询字符串参数和值的解析后的对象。如果parsequerystring设置为true,那么就是解析后的对象
- search url的查询字符串部分,包括前导的问号
- pathname url的路径部分(包括最初的斜线,如果存在的话)
- port 主机的端口号
- hostname 主机的主机名,小写
- auth url的身份认证信息
- host url的完整主机部分,包括端口信息,小写
- protocol 请求协议
- href 这是最初解析的完整的url字符串
- hash url的散列部分,包括井号
2.解析url组件
url模块有用的一种功能就是用与浏览器相同的方式来解析url的组件,这可以让你在服务器端操作url字符串,以在url中作出调整。
把一个url解析到新的位置:
url.resolve(from,to)
其中,from指定了原始基础url字符串,to指定了想要url被解析到的新位置。
举个例子:
var url=require('url'); var originalurl='http://user:pass@host:80/resource/path?query=string#hash'; var newresource='/another/path?querynew'; console.log(url.resolve(originalurl,newresource));
3.处理查询字符串和表单参数
http请求通常在url中包含查询字符串(由url对象获得)或在正文内包含参数数据来处理表单的提交(从客户端请求的正文读出)。查询字符串和表单参数都只是基本的键值对,需要使用querystring模块的parse()方法将字符串转换成javascript对象:
querystring.parse(str,[sep],[eq],[options])
str是查询或参数字符串,sep参数允许你指定使用的分隔符,默认的分隔符是&,eq参数允许你指定分析时使用的赋值运算符,默认值为=,options参数是一个具有属性maxkeys的对象,它能够让你限制生成的对象可以包含的键的数量,默认是1000。
var qstring=require('querystring'); var params=qstring.parse('name=braad&color=red&color=blue'); console.log(params);
4.请求、响应和服务器对象
(1) http.clientrequest对象
当你构建一个http客户端时,调用http.request()使得一个clientrequest对象在内部被创建,这个对象是为了当该请求在服务器上进展的时候来表示它。通常使用clientrequest对象来启动、监控和处理来自服务器的响应。
实现clientrequest对象:
http.request(options,callback)
其中,options参数是一个对象,其属性定义了如何把客户端的http请求打开并发送到服务器,包括host,path,method,port等属性。callback是一个回调函数,在把请求发送到服务器后,处理从服务器返回的响应时调用此回调函数,此回调函数唯一的参数是一个incomingmessage对象,该对象是来自服务器的响应。
一个clientrequest对象的基本实现:
var http=require('http'); var options={ hostname:'www.myserver.com', path:'/', port:'8080', method:'post' }; var req=http.request(options,function(response){ var str=''; response.on('data',function(chunk){ str+=chunk; }); response.on('end',function(){ console.log(str); }); }); req.end();
clientrequest对象的方法:
- write(chunk,[encoding]) 把一个正文数据块(buffer或string对象)写入请求
- end([data],[encoding]) 把可选的数据写入请求正文,然后刷新writeable流并终止该请求
- abort() 终止当前的请求
- settimeout(timeout,[callback]) 为请求设置套接字超时时间
- setnodelay([nodelay]) 禁用在发送数据之前缓冲数据的nagle算法,nodelay是一个布尔值,true表示立即写,false表示缓冲写入
- setsocketkeepalive([enable],[initialdelay]) 启用和禁用对客户机请求的保持活动功能,enable默认为false,即禁用;initialdelay指定最后一个数据包和第一个保持活动请求之间的延迟
(2)http.serverresponse对象
当http服务器接收到一个request事件时,它在内部创建serverresponse对象,这个对象作为第二个参数被传递到request事件处理程序。可以使用serverresponse对象指定并发送到客户端的响应。
serverresponse对象的方法:
- writecontinue() 发送一个http/1.1 100 continue消息给客户端,请求被发送的正文内容
- writehead(statuscode,[reasonphrase],[headers]) 把一个响应标头写入请求,例如response.writehead(200,'successs',{'content-length':body.length,'content-type':'text/plain'});
- settimeout(timeout,[callback]) 设置客户端连接的套接字超时时间
- setheader(name,value) 设置一个特定的标头值
- getheader(name) 获取已在响应中设置的一个http标头
- removeheader(name) 移除已在响应中设置的一个http标头
- write(chunk,[encoding]) 写入chunk,buffer或string对象到响应writeable流,仅把数据写入响应的正文部分
- addtrailers(headers) 将http尾随标头写入响应的结束处
- end([data],[encoding]) 把可选的数据输出写入响应的正文,然后刷新writeable流并响应该请求
(3)http.incomingmessage对象
http服务器和客户端都创建incomingmessage对象,该对象实现了readable流,让你能够把客户端请求或服务器响应作为流院读入,这意味着它们的readable和data事件可以被监听并用来从流中读出数据。
incomingmessage对象中可用的事件、属性和方法
- close 当底层套接字被关闭时发出
- httpversion 指定用于构建客户端请求/响应的http版本
- headers 包含了随请求/响应发送的标头的一个对象
- method 指定用于请求/响应的方法
- url 发送到服务器的url字符串
- statuscode 指定来自服务器的3位数状态码
- socket 一个指向net.socket对象的句柄,用来与客户端/服务器的通信
- settimeout(timeout,[callback]) 设置连接的套接字超时时间
(4)http server对象
http server对象提供了实现http服务器的基本框架,它提供了一个监听端口的底层套接字和接收请求,然后发送响应给客户端连接的处理程序,当服务器正在监听时,node应用程序并没有结束。
要启动http服务器,首先需要createserver()方法创建一个server对象:
http.createserver([requestlistener])
此方法返回server对象,requestlistener参数是在请求事件被触发时执行的回调函数,此回调函数接收两个参数,一个是代表客户端请求的incomingmessage对象,第二个参数是用来指定和发送响应的serverresponse对象。
创建了server对象,就可以在server对象上的listen()方法开始监听它:
listen(port,[hostname],[backlog],[callback])
一个基本的例子:
var http=require('http'); http.createserver(function(req,res){ //handle resquest and response }).listen(8080);
实现一个基本的静态文件服务
//实现一个静态文件服务器 var fs=require('fs'); var http=require('http'); var url=require('url'); //创建一个服务器 http.createserver(function(req,res){ if(req.url!="/favicon.ico"){ var urlobj=url.parse(req.url,true,false); console.log(urlobj.pathname); fs.readfile('.'+urlobj.pathname+'.html',function(err,data){ if(err){ res.writehead(404); res.end(json.stringify(err)); return; } console.log(data.tostring()); //将文件的内容写入res响应对象 res.end(data); }); } }).listen(8080); //实现一个http客户端,向服务器发送一个get请求来检索文件内容 var options={ hostname:'127.0.0.1', port:'8080', path:'/aaa' }; //on('data')读取来自服务器的响应中的内容,on('end')把文件内容记录到到一个文件 function handleresponse(response){ var serverdata=''; response.on('data',function(chunk){ serverdata+=chunk; }); response.on('end',function(){ console.log(serverdata); }); } http.request(options,function(response){ handleresponse(response); }).end();
实现动态的get服务器
var http=require('http'); var messages=[ 'message1', 'message2', 'message3' ]; http.createserver(function(req,res){ res.setheader('content-type','text/html'); res.writehead(200); res.write('<html><head><title>http server</title></head>'); res.write('<body>'); for(var idx in messages){ res.write('\n<h1>'+messages[idx]+'</h1>'); } res.end('\n</body></html>'); }).listen(8080); var options={ hostname:'localhost', port:'8080' }; function handleresponse(response){ var serverdata=''; response.on('data',function(chunk){ serverdata+=chunk; }); response.on('end',function(){ console.log('response status: ',response.statuscode); console.log('response headers: ',response.headers); console.log(serverdata); }); } http.request(options,function(response){ handleresponse(response); }).end();
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。