Node之HTTP服务器创建服务器和获取客户端请求数据

创建HTTP服务器

在Node.js中,可以很方便地创建一个HTTP服务器,只需调用http模块中的create Server方法即可

var server=http.createServer([requestListener])

在createServer方法中,可以使用一个可选参数,参数值为一个回调函数,用于指定当接收到客户端请求时所需执行的处理,该回调函数的指定方法如下所示。

function (request,response) {
//回调函数代码略
}

  • request:代表一个客户端请求
  • response:代表一个服务器端响应对象

createServer方法返回被创建的服务器对象,如果不在createServer方法中使用参数,也可以通过监听该方法创建的服务器对象的request事件(当接收到客户端请求时触发),并且指定该事件触发时调用的回调函数的方法来指定当接收到客户端请求时所需执行的处理,代码如下所示(代码中的server代表一个HTTP服务器)。

server.on('request',function(request,response){
    //回调函数代码略
});

在创建了HTTP服务器后,需要指定该服务器所要监听的地址(可以为一个IP地址,也可以为一个主机名)及端口,这时,可以使用该HTTP服务器的listen方法

server.listen(port,[host],[backlog],[callback])
  • port:端口号
  • host:主机
  • backlog:最大连接数
  • callback:回调

也可使用listening事件实现

server.on('listening',function(){
    //回调函数代码略
});

创建一个服务器完整示例:

var http = require('http');
var server=http.createServer(function (req, res) {
    //暂不指定接收到客户端请求时的处理
}).listen(1337, "127.0.0.1",function(){
    console.log('服务器端开始监听。');
});

close()关闭服务器

server.close();

可以监听服务器被关闭以后

server.on('close',function(){
    //回调函数代码略
});

监听服务器错误信息

server.on('error', function (e) {
    if (e.code == 'EADDRINUSE') {//当地址及端口被占用时错误代码为'EADDRINUSE'
        //可以在此处指定当地址及端口被占用时所需执行的处理
    }
});

长链接

在默认情况下,客户端和服务器端每进行一次HTTP操作,都将建立一次连接,客户端与服务器端之间的交互通信完成后该连接就中断。在HTTP1.1中,添加了长连接支持。如果客户端发出的请求头信息或者服务器端发出的响应头信息中加入了“Connection:keep-alive”信息,则HTTP连接将继续保持,客户端可以继续通过相同的连接向服务器端发出请求。

在Node.js中,当客户端与服务器端建立连接时,触发HTTP服务器对象的connection事件,可以监听该事件并在该事件触发时调用的回调函数中指定当连接建立时所需要执行的处理

server.on('connection',function(socket){
    //回调函数代码略
});

在该回调函数中可以使用一个参数,参数值为服务器端用于监听客户端请求的socket端口对象。

设置服务器的超时时间

可以使用HTTP服务器的setTimeout方法来设置服务器的超时时间。当该超时时间超过之后,客户端不可继续利用本次与HTTP服务器建立的连接,下次向该HTTP服务器发出请求时必须重新建立连接。

server.setTimeout(msecs, callback)
  • mecs:参数值为一个整数,用于设置服务器的超时时间,单位为毫秒,可以通过将该参数值设置为0的方法取消服务器的超时处理。
  • callback:用于设置当服务器超时时调用的回调函数,在该回调函数中可以使用一个参数,参数值为服务器端用于监听客户端请求的socket对象。
server.on('timeout',function(socket){
    //回调函数代码略
});

获取客户端请求信息

HTTP服务器接收到客户端请求时调用的回调函数中的第一个参数值为一个http.IncomingMessage对象,该对象用于读取客户端请求流中的数据,因此,当从客户端请求流中读取到新的数据时触发data事件,当读取完客户端请求流中的数据时触发end事件。当该对象被用于读取客户端请求流中的数据时,该对象拥有如下所示的一些属性。

  • method:该属性值为一个字符串,字符串值为客户端向服务器端发送请求时使用的方法,例如“GET”、“POST”、“PUT”或“DELETE”。
  • url:该属性值为客户端发送请求时使用的URL参数字符串,例如“/”、“/user/1”、“/post/new/?param=value”。该属性为一个非常重要的属性,通常用来判断客户端请求的页面及需要执行的处理。
  • headers:该属性值为客户端发送的请求头对象,其中存放了客户端发送的所有请求头信息,包括各种cookie信息以及浏览器的各种信息。
  • httpVersion:该属性值为一个字符串,字符串值为客户端发送的HTTP版本,可能的值为“1.1”或“1.0”。
  • trailers:该属性值为客户端发送的trailer对象。该对象中存放了客户端附加的一些HTTP头信息,该对象被包含在客户端发送的请求数据之后,因此只有当http.IncomingMessage对象的end事件触发之后才能读取到trailer对象中的信息。
  • socket:该属性值为服务器端用于监听客户端请求的socket对象。

获取请求数据

var http = require('http');
var fs = require('fs');
var server=http.createServer(function (req, res) {
    if(req.url!=="/favicon.ico"){
        req.on('data',function(data){
        console.log('服务器端接收到数据:'+decodeURIComponent(data));
        });
        req.on('end',function(){
        console.log('客户端请求数据已全部接收完毕。');
        });
    }
    res.end();
}).listen(1337, "127.0.0.1");

转换URL字符串与查询字符串

在Node.js中,提供了一个url模块与一个QueryString模块,分别用来转换完整URL字符串与URL中的查询字符串。

在一个完整的URL字符串中,从“?”字符之后(不包括“?”字符)到“#”字符之前(如果存在“#”字符)或者到该URL字符串结束(如果不存在“#”字符)的这一部分称为查询字符串,例如在“http://google.com/user.php?userName=Lulingniu&age=40&sex=male#hash”这个URL字符串中,“userName=Lulingniu&age=40&sex=male”这个部分称为一个查询字符串。

Query String模块中的parse方法

可以使用Query String模块中的parse方法将该字符串转换为一个对象

querystring.parse(str,[sep],[eq],[options])
  • str:用于指定被转换的查询字符串;
  • sep:用于指定该查询字符串中的分割字符,默认参数值为“&”
  • eq:用于指定该查询字符串中的分配字符,默认参数值为“=”
  • options:options参数值为一个对象,可以在该对象中使用一个整数值类型的maxKeys属性来指定转换后的对象中的属性个数,如果将maxKeys属性值设定为0,其效果等于不使用maxKeys属性值。

Query String模块中的stringify方法

可以使用Query String模块中的stringify方法将对象转换为一个查询字符串

querystring.stringify(obj,[sep],[eq])
  • obj:用于指定被转换的对象;
  • sep:用于指定查询字符串中所使用的分割字符,默认参数值为“&”;
  • eq:用于指定查询字符串中使用的分配字符,默认参数值为“=”。

url.parse()

在url模块中,可以使用parse方法将URL字符串转换为一个对象,根据URL字符串中的不同内容,该对象中可能具有的属性及其含义如下所示。

  • href:被转换的原URL字符串。
  • protocol:客户端发出请求时使用的协议。
  • slashes:在协议与路径中间是否使用“//”分隔符。
  • host:URL字符串中的完整地址及端口号,该地址可能为一个IP地址,也可能为一个主机名。
  • auth:URL字符串中的认证信息部分。
  • hostname:URL字符串中的完整地址,该地址可能为一个IP地址,也可能为一个主机名。
  • port:URL字符串中的端口号。
  • pathname:URL字符串中的路径,不包含查询字符串。
  • search:URL字符串中的查询字符串,包含起始字符“?”。
  • path:URL字符串中的路径,包含查询字符串。
  • query:URL字符串中的查询字符串,不包含起始字符“?”,或根据该查询字符串而转换的对象(根据parse方法所用参数而决定query属性值)。
  • hash:URL字符串中的散列字符串,包含起始字符“#”。
url.parse(urlStr,[parseQueryString])
  • urlStr:用于指定需要转换的URL字符串;
  • parseQueryString:为一个布尔类型的参数,当参数值为true时,内部使用Query String模块将查询字符串转换为一个对象,参数值为false时不执行该转换操作,默认参数值为false。

url.format()

可以使用url模块中的format方法将URL字符串经过转换后的对象还原为一个URL字符串。

url.format(urlObj)

url.resolve()

可以使用resolve方法将两个方法结合成为一个路径

url.resolve(from,to
  • from:起点路径字符串
  • to:参考路径字符串

在resolve方法中,使用两个字符串类型的参数,其中第一个参数为起点路径字符串,第二个参数为参考路径字符串。这两个路径既可为相对路径,也可为绝对路径。该方法返回转换后的路径。

在结合路径时,以第一参数值为起点路径,执行如下所示的转换规则。

  • 如果起点路径为网络路径,参考路径为非网络路径的绝对路径,则返回路径为网络根目录+参考路径。
  • 在其他情况下,如果参考路径为绝对路径,则返回路径为该参考路径。
  • 如果起点路径为一个不以“/”字符结尾的根目录且参考路径为相对路径,则返回路径为:起点路径+“/”+参考路径中去除开头的“./”字符或“../”字符(如果存在的话)后的文字。如果起点路径为一个以“/”字符结尾的根目录且参考路径为相对路径,则返回起点路径+参考路径中去除开头的“./”字符或“../”字符(如果存在的话)后的文字。
  • 如果起点路径为一个不以“/”字符结尾的子目录且参考路径为相对路径,同时开头字符不为“./”或“../”,则返回路径为:起点路径的上层目录+“/”+参考路径。如果起点路径为一个以“/”字符结尾的子目录且参考路径为相对路径,同时开头字符不为“./”或“../”,则返回路径为:起点路径的上层目录+“/”+参考路径。
  • 如果起点路径为一个不以“/”字符结尾的子目录且参考路径为相对路径,同时开头字符为“./”,则返回路径为:起点路径的上层目录+“/”+参考路径中去除开头的“./”字符后的文字。如果起点路径为一个以“/”字符结尾的子目录且参考路径为相对路径,同时开头字符为“./”,则返回起点路径+参考路径中去除开头的“./”字符后的文字。
  • 如果起点路径为一个不以“/”字符结尾的子目录且参考路径为相对路径,同时开头字符为“../”,则返回路径为:起点路径的上层目录的上层目录+“/”+参考路径中去除开头的“../”字符后的文字。如果起点路径为一个以“/”字符结尾的子目录且参考路径为相对路径,同时开头字符为“../”,则返
    回起点路径的上层目录+参考路径中去除开头的“../”字符后的文字。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,193评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,306评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,130评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,110评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,118评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,085评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,007评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,844评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,283评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,508评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,395评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,985评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,630评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,797评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,653评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,553评论 2 352

推荐阅读更多精彩内容

  • 人物介绍 凤止沫 年如玉 沐白 李雅琴 第一章 我叫凤止沫从小就是哥哥慕白养长大的,关于...
    凤止沫阅读 126评论 0 1
  • 秋词二首 自古逢秋悲寂寥,我言秋日胜春朝。 晴空一鹤排云上,便引诗情到碧霄。...
    晋显阅读 488评论 0 0
  • 亲子日记第44天,一年级六班李欣怡妈妈 早上去上班,刚下楼就看见外面下着小雨 ,早上一点都不冷。春天来了,...
    欣怡妈妈阅读 116评论 0 0
  • 今天是教师节,先祝福老师们:节日快乐,你们辛苦啦。 两个闺蜜都是在教师行业,身边很多同学也都从事着神圣的园丁职业。...
    penny胖妮阅读 358评论 1 0
  • 我一直想学却一直没有学成的是英语。上学的时候英语成绩很好,也特别羡慕那些能够流利的跟老外对话的人,所以一直梦想着能...
    遇见橙子阅读 185评论 0 0