************************************************************
*************************http模塊***************************
************************************************************
一绒窑、服務(wù)端
var http = require('http');
var fs = require('fs');
var url = require('url');
// 創(chuàng)建服務(wù)器
http.createServer( function (request, response) {
// 解析請求瞳别,包括文件名
var pathname = url.parse(request.url).pathname;
// 輸出請求的文件名
console.log("Request for " + pathname + " received.");
// 從文件系統(tǒng)中讀取請求的文件內(nèi)容
fs.readFile(pathname.substr(1), function (err, data) {
if (err) {
console.log(err);
// HTTP 狀態(tài)碼: 404 : NOT FOUND
// Content Type: text/plain
response.writeHead(404, {'Content-Type': 'text/html'});
}else{
// HTTP 狀態(tài)碼: 200 : OK
// Content Type: text/plain
response.writeHead(200, {'Content-Type': 'text/html'});
// 響應(yīng)文件內(nèi)容
response.write(data.toString());
}
// 發(fā)送響應(yīng)數(shù)據(jù)
response.end();
});
}).listen(8081);
// 控制臺會輸出以下信息
console.log('Server running at http://127.0.0.1:8081/');
二、客戶端
var http = require('http');
// 用于請求的選項(xiàng)
var options = {
host: 'localhost',
port: '8081',
path: '/index.htm'
};
// 處理響應(yīng)的回調(diào)函數(shù)
var callback = function(response){
// 不斷更新數(shù)據(jù)
var body = '';
response.on('data', function(data) {
body += data;
});
response.on('end', function() {
// 數(shù)據(jù)接收完成
console.log(body);
});
}
// 向服務(wù)端發(fā)送請求
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實(shí)例 res是http.ServerResponse實(shí)例
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的話,則會把當(dāng)前請求放入請求池,方便再利用
Sockets 會從agent's pool 移除當(dāng)觸發(fā)'close' 或者 'agentRemove'事件
如:
http.get(options, (res) => {
// Do stuff
}).on('socket', (socket) => {
socket.emit('agentRemove'); //釋放socket請求
});
(2)或者直接設(shè)置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> 當(dāng)使用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]) 回調(diào)(err, stream).
(5)agent.destroy()
關(guān)閉所有的當(dāng)前agent使用的socks請求,否則客戶端會很長時間才關(guān)閉請求
(6)agent.freeSockets
(7)欠橘?矩肩?agent.getName(options)
(8)agent.maxFreeSockets
(9)agent.maxSockets
(10)agent.requests 還沒有分配給sockets的請求
(11)agent.sockets 正在被agent使用的sockets數(shù)組
3.Class: http.ClientRequest 實(shí)現(xiàn)了 Writable Stream 接口
(1)**http.request()返回,header已經(jīng)被設(shè)置好了
默認(rèn)setHeader(name, value), getHeader(name), removeHeader(name)
(2)事件Event:
'abort'#aborted by the client觸發(fā)
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();
//監(jiān)聽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最大頭數(shù)目
(13)server.setTimeout(msecs, callback) Returns server.
設(shè)置請求超時事件默認(rèn)2分鐘
(14)server.timeout <Number> Default = 120000 (2 minutes)
5.Class: http.ServerResponse 由server創(chuàng)建,非用戶創(chuàng)建
(1)Event: 'close'#
function () { }
(2)Event: 'finish'# //此事件是最后一個被觸發(fā)的
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
開始時候?yàn)閒alse. 當(dāng)調(diào)用完response.end(), 就變?yōu)榱?true.
(6)response.getHeader(name)
如:var contentType = response.getHeader('content-type');
(7)response.removeHeader(name)
如:response.removeHeader('Content-Encoding');
(8)response.sendDate 默認(rèn) 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優(yōu)先執(zhí)行
// 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創(chuàng)建黍檩,作為'request' and 'response' event 第一個參數(shù)
用來獲得respose的status, headers and data.實(shí)現(xiàn)了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' }