http中请求request和响应response信息说明
Request
http.ServerRequest 是 HTTP请求的信息,是后端开发者最关注的内容。
它一般由http.Server 的 request 事件发送,作为第一个参数传递,
通常简称request 或 req。
HTTP 请求一般可以分为两部分:
请求头(Request Header)
请求体(Requset Body)
以上内容由于长度较短都可以在请求头解析完成后立即读取。
而请求体可能相对较长,需要一定的时间传输,
因此 http.ServerRequest 提供了以下4个事件用于控制请求体传输。
事件 含义
data 当请求体数据到来时,该事件被触发。该事件提供一个参数
chunk 表示接收到的数据。如果该事件没有被监听,那么请求体将会被抛弃。该事件可能会被调用多次。
end 当请求体数据传输完成时,该事件被触发,此后将不会再有数据到来。
close 用户当前请求结束时,该事件被触发。不同于end,如果用户强制终止了传输,也还是调用close
ServerRequest 的属性
事件 含义
complete 客户端请求是否已经发送完成
httpVersion HTTP 协议版本,通常是 1.0 或 1.1
method HTTP 请求方法,如 GET、POST、PUT、DELETE 等
url 原始的请求路径
headers HTTP 请求头
trailers HTTP 请求尾(不常见)
connection 当前 HTTP 连接套接字,为 net.Socket 的实例
socket connection 属性的别名
client client 属性的别名
Response
http.ClientResponse 与 http.ServerRequest 相似,
提供了三个事件data、end和close,
分别在数据到达、传输结束和连接结束时触发,
其中data事件传递一个参数chunk,表示接收到的数据。
ClientResponse 的属性
名称 含义
statusCode HTTP 状态码,如 200、404、500
httpVersion HTTP 协议版本,通常是 1.0 或 1.1
headers HTTP 请求头
trailers HTTP 请求尾(不常见)
Header 头详解
HTTP(HyperTextTransferProtocol)即超文本传输协议,目前网页传输的的通用协议。
HTTP协议采用了请求/响应模型,浏览器或其他客户端发出请求,服务器给与响应。
就整个网络资源传输而言,包括message-header和message-body两部分。
首先传递message- header,即http header消息 。
http header 消息通常被分为4个部分:general header, request header, response header, entity header。
但是这种分法就理解而言,感觉界限不太明确。
根据维基百科对http header内容的组织形式,大体分为Request和Response两部分。
Requests部分
Header 解释 示例
Accept 指定客户端能够接收的内容类型 Accept: text/plain, text/html
Accept-Charset 浏览器可以接受的字符编码集。 Accept-Charset: iso-8859-5
Accept-Encoding 指定浏览器可以支持的web服务器返回内容压缩编码类型。 Accept-Encoding: compress, gzip
Accept-Language 浏览器可接受的语言 Accept-Language: en,zh
Accept-Ranges 可以请求网页实体的一个或者多个子范围字段 Accept-Ranges: bytes
Authorization HTTP授权的授权证书 Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Cache-Control 指定请求和响应遵循的缓存机制 Cache-Control: no-cache
Connection 表示是否需要持久连接。(HTTP 1.1默认进行持久连接) Connection: close
Cookie HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。 Cookie: $Version=1; Skin=new;
Content-Length 请求的内容长度 Content-Length: 348
Content-Type 请求的与实体对应的MIME信息 Content-Type: application/x-www-form-urlencoded
Date 请求发送的日期和时间 Date: Tue, 15 Nov 2010 08:12:31 GMT
Expect 请求的特定的服务器行为 Expect: 100-continue
From 发出请求的用户的Email From: user@email.com
Host 指定请求的服务器的域名和端口号 Host: www.zcmhi.com
If-Match 只有请求内容与实体相匹配才有效 If-Match: “737060cd8c284d8af7ad3082f209582d”
If-Modified-Since 如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码 If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT
If-None-Match 如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变 If-None-Match: “737060cd8c284d8af7ad3082f209582d”
If-Range 如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。 参数也为Etag If-Range: “737060cd8c284d8af7ad3082f209582d”
If-Unmodified-Since 只在实体在指定时间之后未被修改才请求成功 If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT
Max-Forwards 限制信息通过代理和网关传送的时间 Max-Forwards: 10
Pragma 用来包含实现特定的指令 Pragma: no-cache
Proxy-Authorization 连接到代理的授权证书 Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Range 只请求实体的一部分,指定范围 Range: bytes=500-999
Referer 先前网页的地址,当前请求网页紧随其后,即来路 Referer: http://www.baidu.com
TE 客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息 TE: trailers,deflate;q=0.5
Upgrade 向服务器指定某种传输协议以便服务器进行转换(如果支持) Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
User-Agent User-Agent的内容包含发出请求的用户信息 User-Agent: Mozilla/5.0 (Linux; X11)
Via 通知中间网关或代理服务器地址,通信协议 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning 关于消息实体的警告信息 Warn: 199 Miscellaneous warning
Responses 部分
Header 解释 示例
Accept-Ranges 表明服务器是否支持指定范围请求及哪种类型的分段请求 Accept-Ranges: bytes
Age 从原始服务器到代理缓存形成的估算时间(以秒计,非负) Age: 12
Allow 对某网络资源的有效的请求行为,不允许则返回405 Allow: GET, HEAD
Cache-Control 告诉所有的缓存机制是否可以缓存及哪种类型 Cache-Control: no-cache
Content-Encoding web服务器支持的返回内容压缩编码类型。 Content-Encoding: gzip
Content-Language 响应体的语言 Content-Language: en,zh
Content-Length 响应体的长度 Content-Length: 348
Content-Location 请求资源可替代的备用的另一地址 Content-Location: /index.htm
Content-MD5 返回资源的MD5校验值 Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==
Content-Range 在整个返回体中本部分的字节位置 Content-Range: bytes 21010-47021/47022
Content-Type 返回内容的MIME类型 Content-Type: text/html; charset=utf-8
Date 原始服务器消息发出的时间 Date: Tue, 15 Nov 2010 08:12:31 GMT
ETag 请求变量的实体标签的当前值 ETag: “737060cd8c284d8af7ad3082f209582d”
Expires 响应过期的日期和时间 Expires: Thu, 01 Dec 2010 16:00:00 GMT
Last-Modified 请求资源的最后修改时间 Last-Modified: Tue, 15 Nov 2010 12:45:26 GMT
Location 用来重定向接收方到非请求URL的位置来完成请求或标识新的资源 Location: http://www.zcmhi.com/archives/94.html
Pragma 包括实现特定的指令,它可应用到响应链上的任何接收方 Pragma: no-cache
Proxy-Authenticate 它指出认证方案和可应用到代理的该URL上的参数 Proxy-Authenticate: Basic
refresh 应用于重定向或一个新的资源被创造,在5秒之后重定向(由网景提出,被大部分浏览器支持) Refresh: 5; url= http://www.zcmhi.com/archives/94.html
Retry-After 如果实体暂时不可取,通知客户端在指定时间之后再次尝试 Retry-After: 120
Server web服务器软件名称 Server: Apache/1.3.27 (Unix) (Red-Hat/Linux)
Set-Cookie 设置Http Cookie Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1
Trailer 指出头域在分块传输编码的尾部存在 Trailer: Max-Forwards
Transfer-Encoding 文件传输编码 Transfer-Encoding:chunked
Vary 告诉下游代理是使用缓存响应还是从原始服务器请求 Vary: *
Via 告知代理客户端响应是通过哪里发送的 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
关于HTTP部分大致分为如下的重要点:
直接通过http对象使用的有:
http.STATUS_CODES
http.createServer
http.request(http.ClientRequest)
http.get
http.globalAgent
http.IcomingMessage
作为回调参数使用的对象有:
http.serverRequest
http.serverResponse
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'
}
}
测试用例:
var http = require('http');
http.createServer(function(req, res) {
var status = 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.代码如下。
// 引入 http 模块
var http = require('http');
/**
* 创建服务器的两种写法,第一种写法如下
* 由于server已经继承了EventEmitter的事件功能,所以可以使用高级函数编写方式监控事件
* @param {Function} request event
*/
var server = http.createServer(function(req, res) {
//这里的req为http.serverRequest
res.writeHeader(200, {
'Content-Type': 'text/plain'
});
res.end('hello world');
});
/**
* 说明:创建服务器的第二种写法
* 有关server对象的事件监听
* @param {Object} req 是http.IncomingMessag的一个实例,在keep-alive连接中支持多个请求
* @param {Object} res 是http.ServerResponse的一个实例
*/
var server = new http.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 是一个类似关联数组的对象,表示请求的参数,-option常用的参数如下所示。
callback 是请求的回调函数。
http.request 返回一个 http.ClientRequest 的实例。
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事件的同时设置超时。参见RFC2616 8.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 {Object or String} 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 {Object or String} 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()。
var http = 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);
})