Node.js HTTP 使用详解

本文转自 http://my.oschina.net/antianlu/blog/228511

摘要

翻译和注释了http 模块,讲述输入使用,在什么地方写代码

于初学者有没有发觉在查看Node.js官方API的时候非常简单,只有几个洋文描述两下子,没了,我第一次一口气看完所以API后,对于第一个示例都有些懵,特别是参数里的request和response,究竟是如何通过参数工作的,如果并发量大如何确保每个人访问和提交的数据不干扰等等。都没有教你具体如何在开发中使用,如何着手写代码,给你一个Event 'close',只说了下在服务器关闭时触发,完了。如果没有了解EventEmitter的核心事件,可能还真不知道如何抒写代码并在开发中真正使用。而http server创建的服务对象已经继承了EventEmitter,所以可以直接使用on进行监听即可。学学util包中的inherits是如何继承EventEmitter的就应该略知一二了。

在官方文档的API中有服务器对象和回调函数参数返回参数的对象,response和request对象各有两种不同。一种是server级别的一种是client级别的。

关于HTTP部分大致分为如下的重要点:

直接通过http对象使用的有:

一、http.STATUS_CODES

二、http.createServer

三、http.request(http.ClientRequest)

四、http.get

五、http.globalAgent

六、http.IcomingMessage

作为回调参数使用的对象有:

1.http.serverRequest

2.http.serverResponse

3.http.Agent

一、http.STATUS_CODES

众所周知,http服务器就是一个状态服务器,可以根据状态码来确定服务器是处于请求的什么状态。如下列出Node.js status code的全部状态对于的解释。

http: {STATUS_CODES: {'100':'Continue','101':'Switching Protocols','102':'Processing','200':'OK','201':'Created','202':'Accepted','203':'Non-Authoritative Information','204':'No Content','205':'Reset Content','206':'Partial Content','207':'Multi-Status','300':'Multiple Choices','301':'Moved Permanently','302':'Moved Temporarily','303':'See Other','304':'Not Modified','305':'Use Proxy','307':'Temporary Redirect','400':'Bad Request','401':'Unauthorized','402':'Payment Required','403':'Forbidden','404':'Not Found','405':'Method Not Allowed','406':'Not Acceptable','407':'Proxy Authentication Required','408':'Request Time-out','409':'Conflict','410':'Gone','411':'Length Required','412':'Precondition Failed','413':'Request Entity Too Large','414':'Request-URI Too Large','415':'Unsupported Media Type','416':'Requested Range Not Satisfiable','417':'Expectation Failed','418':'I\'m a teapot','422':'Unprocessable Entity','423':'Locked','424':'Failed Dependency','425':'Unordered Collection','426':'Upgrade Required','428':'Precondition Required','429':'Too Many Requests','431':'Request Header Fields Too Large','500':'Internal Server Error','501':'Not Implemented','502':'Bad Gateway','503':'Service Unavailable','504':'Gateway Time-out','505':'HTTP Version Not Supported','506':'Variant Also Negotiates','507':'Insufficient Storage','509':'Bandwidth Limit Exceeded','510':'Not Extended','511':'Network Authentication Required'}}

测试用例:

varhttp =require('http');http.createServer(function(req,res){varstatus = req.url.substr(1);if( ! http.STATUS_CODES[status])    {        status ='404';    }    res.writeHeader(status,{'Content-Type':'text/plain'});    res.end(http.STATUS_CODES[status]);}).listen(3000);

测试连接:http://localhost:3000/500结果输出Internal Server Error

二、http.createServer

http.createServer是创建一台web服务器的关键所在,是处理请求和回应的主函数出口和出口,我们把http.createServer创建的服务对象定义为server.代码如下。

/**

* Created by Administrator on 14-4-29.

*/varhttp =require('http');/**

* 创建服务器的两种写法,第一种写法如下

* 由于server已经继承了EventEmitter的事件功能,所以可以使用高级函数编写方式监控事件

*@param{Function} request event

*/varserver = http.createServer(function(req,res){//这里的req为http.serverRequestres.writeHeader(200,{'Content-Type':'text/plain'});    res.end('hello world');});/**

* 说明:创建服务器的第二种写法

* 有关server对象的事件监听

*@param{Object} req 是http.IncomingMessag的一个实例,在keep-alive连接中支持多个请求

*@param{Object} res 是http.ServerResponse的一个实例

*/varserver =newhttp.Server();server.on('request',function(req,res){    res.writeHeader(200,{'Content-Type':'text/plain'});    res.end('hello world');});/**

* 说明:新的TCP流建立时出发。 socket是一个net.Socket对象。 通常用户无需处理该事件。

* 特别注意,协议解析器绑定套接字时采用的方式使套接字不会出发readable事件。 还可以通过request.connection访问socket。

*@param{Object} socket

*/server.on('connection',function(socket){});/**

* 源API: Event: 'close'

* 说明:关闭服务器时触发

*/server.on('close',function(){});/**

* 说明:每当收到Expect: 100-continue的http请求时触发。 如果未监听该事件,服务器会酌情自动发送100 Continue响应。

* 处理该事件时,如果客户端可以继续发送请求主体则调用response.writeContinue, 如果不能则生成合适的HTTP响应(例如,400 请求无效)

* 需要注意到, 当这个事件触发并且被处理后, request 事件将不再会触发.

*@param{Object} req

*@param{Object} req

*/server.on('checkContinue',function(req,res){});/**

* 说明:如果客户端发起connect请求,如果服务器端没有监听,那么于客户端请求的该连接将会被关闭

*@param{Object} req 是该HTTP请求的参数,与request事件中的相同。

*@param{Object} socket 是服务端与客户端之间的网络套接字。需要自己写一个data事件监听数据流

*@param{Object} head 是一个Buffer实例,隧道流的第一个包,该参数可能为空。

*/server.on('connect',function(req,socket,head){});/**

* 说明:这个事件主要是对HTTP协议升级为其他协议后的事件监听,如果服务器端没有监听,那么于客户端请求的该连接将会被关闭

*@param{Object} req 是该HTTP请求的参数,与request事件中的相同。

*@param{Object} socket 是服务端与客户端之间的网络套接字。需要自己写一个data事件监听数据流

*@param{Object} head 是一个Buffer实例,升级后流的第一个包,该参数可能为空。

*/server.on('upgrade',function(req,socket,head){});/**

* 说明:如果一个客户端连接触发了一个 'error' 事件, 它就会转发到这里

*@param{Object} exception

*@param{Object} socket

*/server.on('clientError',function(exception,socket){});/**

* 源API:server.listen(port, [hostname], [backlog], [callback])

* 说明:监听一个 unix socket, 需要提供一个文件名而不是端口号和主机名。

*@param{Number} port 端口

*@param{String} host 主机

*@param{Number} backlog 等待队列的最大长度,决定于操作系统平台,默认是511

*@param{Function} callback 异步回调函数

*///server.listen(3000,'localhost',100,function(){});/**

* 源API:server.listen(path, [callback])

* 说明:启动一个 UNIX 套接字服务器在所给路径 path 上监听连接。

* 可能用处:多路径或渠道数据来源监听分隔

*@param{String} path

*@param{Function} callback

*///server.listen('path',function(){})/**

* 源API:server.listen(handle, [callback])

* 说明:Windows 不支持监听一个文件描述符。

*@param{Object} handle 变量可以被设置为server 或者 socket

*@param{Function} callback

*///server.listen({},function(){});/**

* 说明:最大请求头数目限制, 默认 1000 个. 如果设置为0, 则代表不做任何限制.

*@type{number}

*/server.maxHeadersCount =1000;/**

* 源API:server.setTimeout(msecs, callback)

* 说明:为套接字设定超时值。如果一个超时发生,那么Server对象上会分发一个'timeout'事件,同时将套接字作为参数传递。

* 设置为0将阻止之后建立的连接的一切自动超时行为

*@param{Number} msecs

*@param*/server.setTimeout(1000,function(){});/**

* 说明:一个套接字被判断为超时之前的闲置毫秒数。 默认 120000 (2 分钟)

*@type{number}

*/server.timeout =120000;/**

* 说明:这里的主机将是本地

*@param{Number} port 端口

*@param{Function} callback 异步回调函数

*/server.listen(3000,function(){   console.log('Listen port 3000');});

三 、http.request

http 模块提供了两个函数 http.request 和 http.get,功能是作为客户端向 HTTP服务器发起请求。http.request(options, callback) 发起 HTTP 请求。接受两个参数,option 是一个类似关联数组的对象,表示请求的参数,callback 是请求的回调函数。option常用的参数如下所示。http.request 返回一个 http.ClientRequest 的实例。

/** * Created by Administrator on14-4-30.*/var http =require('http');var server = http.createServer(function(req,res){}).listen(3000);/** * 参数配置 * @type{{hostname:string, port: number, method:string, path:string,handers: {}}} * host:请求的服务器域名或者IP地址 * port:端口 * method:请求方式有POST,GET,INPUT,DELETE,CONNECT,默认为GET * path:请求地址,可包含查询字符串以及可能存在的锚点。例如'/index.html?page=12'* handers: 一个包含请求头的对象。 */var options ={    hostname :'www.google.com',    port :80,    method :'POST',    path :'/upload',    handers:{}};/** * 如下特别的消息头应当注意: * 发送'Connection: keep-alive'头部将通知Node此连接将保持到下一次请求。 * 发送'Content-length'头将使默认的分块编码无效。 * 发送'Expect'头部将引起请求头部立即被发送。 * 通常情况,当发送'Expect: 100-continue'时,你需要监听continue事件的同时设置超时。参见RFC26168.2.3章节以获得更多的信息。 *//** * 说明:官方给出的例子 * 应用场景:模拟客服端请求服务器,是一个HTTP 客户端工具,用于向 HTTP 服务器发起请求。 * @param {Object} options * @param {Function} callback */var req = http.request(options,function(res){    console.log(res);    console.log('STATUS:'+ res.statusCode);    console.log('HEADERS:'+ JSON.stringify(res.headers));    res.setEncoding('utf8');    res.on('data',function(chunk){       console.log('BODY'+ chunk);    });});req.on('response',function(){});req.on('connect',function(){});req.on('socket',function(){});req.on('upgrade',function(){});req.on('continue',function(){})//如果在请求过程中出现了错误(可能是DNS解析、TCP的错误、或者HTTP解析错误),返回的请求对象上的'error'的事件将被触发。req.on('error',function(e){   console.log(e.message);});/** * 源API:request.write(chunk, [encoding]) * 说明:发送正文中的一块。用户可以通过多次调用这个方法将请求正文以流的方式发送到服务器。此种情况建议在建立请求时使用['Transfer-Encoding','chunked']请求头。 * @param {ObjectorString} chunk 参数chunk应当是一个整数数组或字符串。 * @param {String} encoding 参数encoding是可选的,仅在chunk为字符串时可用。 */req.write('data\n');/** * 源API:request.end(chunk, [encoding]) * 说明:完成本次请求的发送。如果正文中的任何一个部分没有来得及发送,将把他们全部刷新到流中。如果本次请求是分块的,这个函数将发出结束字符'0\r\n\r\n'。如果使用参数data,就等于在调用request.write(data, encoding)之后紧接着调用request.end()。 * @param {ObjectorString} chunk 参数chunk应当是一个整数数组或字符串。 * @param {String} encoding 参数encoding是可选的,仅在chunk为字符串时可用。 * example: req.end(),req.end('data\n'),req.end('data','utf8'),req.end(chunk) */req.end();/** * 阻止一个请求。(v0.3.8中新增的方法。) */req.abort();/** * 源API:request.setTimeout(timeout, [callback]) * 说明:一旦给这个请求分配的是一个socket时此函数会被调用 * @param {Number} timeout 毫秒 * @param {Function} callback 回到函数 */req.setTimeout(1000,function(){});/** * 源API :request.setNoDelay([noDelay]) * 说明:默认有一定的延迟,设置为0表示无延迟 * @param {Number} noDelay */req.setNoDelay(0)/** * 源API:request.setSocketKeepAlive([enable], [initialDelay]) *     类似同上 */

四、http.get

http.get(options,

callback) http 模块还提供了一个更加简便的方法用于处理GET请求:http.get。它是 http.request

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

/**

* Created by Administrator on 14-4-30.

*/varhttp =require('http');http.createServer(function(req,res){}).listen(3000);/**

* 说明:由于大部分请求是不包含正文的GET请求,Node提供了这个方便的方法。与http.request()唯一的区别是此方法将请求方式设置为GET,并且自动调用req.end()。

* 应用:服务器端测试客服端请求调试等

*@param{String} url 有效地址

*@param{Function} callback

*/http.get('http://www.baidu.com/index.html',function(res){    console.log('get response Code :'+ res.statusCode);}).on('error',function(e){        console.log("Got error: "+ e.message);    })

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

推荐阅读更多精彩内容