************************************************************
*************************http模块***************************
************************************************************
一、服务端
var http = require('http');
var fs = require('fs');
var url = require('url');
// 创建服务器
http.createServer( function (request, response) {
// 解析请求,包括文件名
var pathname = url.parse(request.url).pathname;
// 输出请求的文件名
console.log("Request for " + pathname + " received.");
// 从文件系统中读取请求的文件内容
fs.readFile(pathname.substr(1), function (err, data) {
if (err) {
console.log(err);
// HTTP 状态码: 404 : NOT FOUND
// Content Type: text/plain
response.writeHead(404, {'Content-Type': 'text/html'});
}else{
// HTTP 状态码: 200 : OK
// Content Type: text/plain
response.writeHead(200, {'Content-Type': 'text/html'});
// 响应文件内容
response.write(data.toString());
}
// 发送响应数据
response.end();
});
}).listen(8081);
// 控制台会输出以下信息
console.log('Server running at http://127.0.0.1:8081/');
二、客户端
var http = require('http');
// 用于请求的选项
var options = {
host: 'localhost',
port: '8081',
path: '/index.htm'
};
// 处理响应的回调函数
var callback = function(response){
// 不断更新数据
var body = '';
response.on('data', function(data) {
body += data;
});
response.on('end', function() {
// 数据接收完成
console.log(body);
});
}
// 向服务端发送请求
var req = http.request(options, callback);
req.end();
三、API
HTTP
http.STATUS_CODES
http.createServer([requestListener])
http.createClient([port], [host])
Class: http.Server
事件 : 'request'
事件: 'connection'
事件: 'close'
事件: 'checkContinue'
事件: 'connect'
事件: 'upgrade'
事件: 'clientError'
server.listen(port, [hostname], [backlog], [callback])
server.listen(path, [callback])
server.listen(handle, [callback])
server.close([callback])
server.maxHeadersCount
server.setTimeout(msecs, callback)
server.timeout
Class: http.ServerResponse
事件: 'close'
response.writeContinue()
*response.writeHead(statusCode, [reasonPhrase], [headers])
例子:req是http.IncomingMessage实例 res是http.ServerResponse实例
var server = http.createServer(function(req,res){
res.writeHeader(200,{
'Content-Type' : 'text/plain;charset=utf-8' // 添加charset=utf-8
}) ;
res.end("Hello,大熊!") ;
}) ;
response.setTimeout(msecs, callback)
response.statusCode
*response.setHeader(name, value)
response.headersSent
response.sendDate
*response.getHeader(name)
response.removeHeader(name)
*response.write(chunk, [encoding])
response.addTrailers(headers)
*response.end([data], [encoding])
http.request(options, callback)
http.get(options, callback)
Class: http.Agent
new Agent([options])
agent.maxSockets
agent.maxFreeSockets
agent.sockets
agent.freeSockets
agent.requests
agent.destroy()
agent.getName(options)
http.globalAgent
Class: http.ClientRequest
事件 'response'
事件: 'socket'
事件: 'connect'
事件: 'upgrade'
事件: 'continue'
request.write(chunk, [encoding])
request.end([data], [encoding])
request.abort()
request.setTimeout(timeout, [callback])
request.setNoDelay([noDelay])
request.setSocketKeepAlive([enable], [initialDelay])
http.IncomingMessage
事件: 'close'
message.httpVersion
message.headers
message.rawHeaders
message.trailers
message.rawTrailers
message.setTimeout(msecs, callback)
message.method
message.url
message.statusCode
message.socket
//例子
http.createServer(function (request, response) {
var body = [];
console.log(request.method) ;
console.log(request.headers) ;
request.on('data', function (chunk) {
body.push(chunk);
}) ;
request.on('end', function () {
body = Buffer.concat(body) ;
console.log(body.toString()) ;
});
}).listen(8888) ;
/*{ accept: 'text/html, application/xhtml+xml, image/jxr, */*',
'accept-language': 'zh-Hans-CN,zh-Hans;q=0.5',
'user-agent': 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 10.0; WOW64; Trident/7.0)',
'accept-encoding': 'gzip, deflate',
host: 'localhost:8888',
connection: 'Keep-Alive' }*/
1.http头格式
{ 'content-length': '123',
'content-type': 'text/plain',
'connection': 'keep-alive',
'host': 'mysite.com',
'accept': '*/*' }
2.Class: http.Agent
(1)如果 HTTP KeepAlive的话,则会把当前请求放入请求池,方便再利用
Sockets 会从agent's pool 移除当触发'close' 或者 'agentRemove'事件
如:
http.get(options, (res) => {
// Do stuff
}).on('socket', (socket) => {
socket.emit('agentRemove'); //释放socket请求
});
(2)或者直接设置agent:false,就会直接释放
http.get({
hostname: 'localhost',
port: 80,
path: '/',
agent: false // create a new agent just for this one request
}, (res) => {
// Do stuff with response
})
(3)new Agent([options]
options <Object>
keepAlive <Boolean> 放入pool 可以被其他请求使用 Default = false
keepAliveMsecs <Integer> 当使用HTTP KeepAlive=true时使用, Default = 1000.
maxSockets <Number> sockets允许请求host的最大值. Default = Infinity.
maxFreeSockets <Number> sockets请求的最大值. keepAlive=true. Default = 256
例子:
const http = require('http');
var keepAliveAgent = new http.Agent({ keepAlive: true });
options.agent = keepAliveAgent;
http.request(options, onResponseCallback);
(4)agent.createConnection(options[, callback]) 回调(err, stream).
(5)agent.destroy()
关闭所有的当前agent使用的socks请求,否则客户端会很长时间才关闭请求
(6)agent.freeSockets
(7)??agent.getName(options)
(8)agent.maxFreeSockets
(9)agent.maxSockets
(10)agent.requests 还没有分配给sockets的请求
(11)agent.sockets 正在被agent使用的sockets数组
3.Class: http.ClientRequest 实现了 Writable Stream 接口
(1)**http.request()返回,header已经被设置好了
默认setHeader(name, value), getHeader(name), removeHeader(name)
(2)事件Event:
'abort'#aborted by the client触发
function () { }
'checkExpectation'#
function (request, response) { }
'connect'#
function (response, socket, head) { }
(3)例子
const http = require('http');
const net = require('net');
const url = require('url');
// Create an HTTP tunneling proxy
var proxy = http.createServer( (req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('okay');
});
proxy.on('connect', (req, cltSocket, head) => {
// connect to an origin server
var srvUrl = url.parse(`http://${req.url}`);
var srvSocket = net.connect(srvUrl.port, srvUrl.hostname, () => {
cltSocket.write('HTTP/1.1 200 Connection Established\r\n' +
'Proxy-agent: Node.js-Proxy\r\n' +
'\r\n');
srvSocket.write(head);
srvSocket.pipe(cltSocket);
cltSocket.pipe(srvSocket);
});
});
// now that proxy is running
proxy.listen(1337, '127.0.0.1', () => {
// make a request to a tunneling proxy
var options = {
port: 1337,
hostname: '127.0.0.1',
method: 'CONNECT',
path: 'www.google.com:80'
};
var req = http.request(options);
req.end();
//监听connect事件
req.on('connect', (res, socket, head) => {
console.log('got connected!');
// make a request over an HTTP tunnel
socket.write('GET / HTTP/1.1\r\n' +
'Host: www.google.com:80\r\n' +
'Connection: close\r\n' +
'\r\n');
socket.on('data', (chunk) => {
console.log(chunk.toString());
});
socket.on('end', () => {
proxy.close();
});
});
});
(4)Event: 'continue'#
function () { }
(5)Event: 'response'#
function (response) { }
(6)Event: 'socket'#
function (socket) { }
(7)Event: 'upgrade'#
function (response, socket, head) { }
(8)例子
const http = require('http');
// Create an HTTP server
var srv = http.createServer( (req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('okay');
});
srv.on('upgrade', (req, socket, head) => {
socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
'Upgrade: WebSocket\r\n' +
'Connection: Upgrade\r\n' +
'\r\n');
socket.pipe(socket); // echo back
});
// now that server is running
srv.listen(1337, '127.0.0.1', () => {
// make a request
var options = {
port: 1337,
hostname: '127.0.0.1',
headers: {
'Connection': 'Upgrade',
'Upgrade': 'websocket'
}
};
var req = http.request(options);
req.end();
req.on('upgrade', (res, socket, upgradeHead) => {
console.log('got upgraded!');
socket.end();
process.exit(0);
});
});
(9)request.abort()
(10)request.end([data][, encoding][, callback])
(11)request.flushHeaders()
(12)request.setNoDelay([noDelay])
(13)request.setSocketKeepAlive([enable][, initialDelay])
(14)request.setTimeout(timeout[, callback])
(15)request.write(chunk[, encoding][, callback])
4.Class: http.Server
(1)Event: 'checkContinue'#
function (request, response) { }
(2)Event: 'clientError'#
function (exception, socket) { }
(3)Event: 'close'#
function () { }
(4)Event: 'connect'#
function (request, socket, head) { }
(5)Event: 'connection'#
function (socket) { }
(6)Event: 'request'#
function (request, response) { }
(7)Event: 'upgrade'#
function (request, socket, head) { }
(8)server.close([callback])
(9)server.listen(handle[, callback])
(10)server.listen(path[, callback])
(11)server.listen(port[, hostname][, backlog][, callback])
(12)server.maxHeadersCount最大头数目
(13)server.setTimeout(msecs, callback) Returns server.
设置请求超时事件默认2分钟
(14)server.timeout <Number> Default = 120000 (2 minutes)
5.Class: http.ServerResponse 由server创建,非用户创建
(1)Event: 'close'#
function () { }
(2)Event: 'finish'# //此事件是最后一个被触发的
function () { }
(3)response.addTrailers(headers) 注意http1.0废弃
如:response.writeHead(200, { 'Content-Type': 'text/plain',
'Trailer': 'Content-MD5' });
response.write(fileData);
response.addTrailers({'Content-MD5': '7895bf4b8828b55ceaf47747b4bca667'});
response.end();
(4)response.end([data][, encoding][, callback])
(5)response.finished
开始时候为false. 当调用完response.end(), 就变为了 true.
(6)response.getHeader(name)
如:var contentType = response.getHeader('content-type');
(7)response.removeHeader(name)
如:response.removeHeader('Content-Encoding');
(8)response.sendDate 默认 true.Date header自动添加
(9)response.setHeader(name, value)
如:response.setHeader('Content-Type', 'text/html');
response.setHeader('Set-Cookie', ['type=ninja', 'language=javascript']);
(10)res.writeHead优先执行
// returns content-type = text/plain
const server = http.createServer((req,res) => {
res.setHeader('Content-Type', 'text/html');
res.setHeader('X-Foo', 'bar');
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('ok');
});
(11)response.setTimeout(msecs, callback) Returns response.
(12)response.statusCode
(13)response.statusMessage = 'Not found';
(14)response.write(chunk[, encoding][, callback])
6.Class: http.IncomingMessage
(1)原理
由http.Server or http.ClientRequest创建,作为'request' and 'response' event 第一个参数
用来获得respose的status, headers and data.实现了Readable Stream接口
(2)包括以下事件
Event: 'close'#
function () { }
(3)message.headers
// Prints something like:
//
// { 'user-agent': 'curl/7.22.0',
// host: '127.0.0.1:8000',
// accept: '*/*' }
console.log(request.headers);
(4)message.httpVersion '1.1' or '1.0'.
(5)message.method 'GET', 'DELETE'.
(6)message.rawHeaders
// Prints something like:
//
// [ 'user-agent',
// 'this is invalid because there can be only one',
// 'User-Agent',
// 'curl/7.22.0',
// 'Host',
// '127.0.0.1:8000',
// 'ACCEPT',
// '*/*' ]
console.log(request.rawHeaders);
(7)http.get(options[, callback])
http.get('http://www.google.com/index.html', (res) => {
console.log(`Got response: ${res.statusCode}`);
// consume response body
res.resume();
}).on('error', (e) => {
console.log(`Got error: ${e.message}`);
});
(8)http.request(options[, callback])
var postData = querystring.stringify({
'msg' : 'Hello World!'
});
var options = {
hostname: 'www.google.com',
port: 80,
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': postData.length
}
};
var req = http.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.')
})
});
req.on('error', (e) => {
console.log(`problem with request: ${e.message}`);
});
// write data to request body
req.write(postData);
req.end();
url解析
'use strict';
var url = require('url');
console.log(url.parse('http://user:pass@host.com:8080/path/to/file?query=string#hash'));
Url {
protocol: 'http:',
slashes: true,
auth: 'user:pass',
host: 'host.com:8080',
port: '8080',
hostname: 'host.com',
hash: '#hash',
search: '?query=string',
query: 'query=string',
pathname: '/path/to/file',
path: '/path/to/file?query=string',
href: 'http://user:pass@host.com:8080/path/to/file?query=string#hash' }