1. HTTP伺服器 #
HTTP全稱是超文字傳輸協議,構建於TCP之上,屬於應用層協議。
1.1 建立HTTP伺服器
let server = http.createServer([requestListener]);
server.on('request',requestListener);
複製程式碼
- requestListener 當伺服器收到客戶端的連線後執行的處理
- http.IncomingMessage 請求物件
- http.ServerResponse物件 伺服器端響應物件
1.2 啟動HTTP伺服器
server.listen(port,[host],[backlog],[callback]);
server.on('listening',callback);
複製程式碼
- port 監聽的埠號
- host 監聽的地址
- backlog 指定位於等待佇列中的客戶端連線數
let http = require('http');
let server = http.createServer(function(req,res){
}).listen(8080,'127.0.0.1',function(){console.log('伺服器端開始監聽!')});
複製程式碼
1.3 關閉HTTP伺服器
server.close();
server.on('close',function(){});
複製程式碼
let http = require('http');
let server = http.createServer(function(req,res){
});
server.on('close',function(){
console.log('伺服器關閉');
});
server.listen(8080,'127.0.0.1',function(){
console.log('伺服器端開始監聽!')
server.close();
});
複製程式碼
1.4 監聽伺服器錯誤
server.on('error',function(){
if(e.code == 'EADDRINUSE'){
console.log('埠號已經被佔用!);
}
});
複製程式碼
1.5 connection
let server = http.createServer(function(req,res){
});
server.on('connection',function(){
console.log(客戶端連線已經建立);
});
複製程式碼
1.6 setTimeout
設定超時時間,超時後不可再複用已經建立的連線,需要發請求需要重新建立連線。預設超時時間時2分鐘
server.setTimeout(msecs,callback);
server.on('timeout',function(){
console.log('連線已經超時');
});
複製程式碼
1.7 獲取客戶端請求資訊
- request
- method 請求的方法
- url 請求的路徑
- headers 請求頭物件
- httpVersion 客戶端的http版本
- socket 監聽客戶端請求的socket物件
let http = require('http'); let fs = require('fs'); let server = http.createServer(function(req,res){ if(req.url != '/favicon.ico'){ let out = fs.createWriteStream(path.join(__dirname,'request.log')); out.write('method='+req.method); out.write('url='+req.url); out.write('headers='+JSON.stringify(req.headers)); out.write('httpVersion='+req.httpVersion); } }).listen(8080,'127.0.0.1); 複製程式碼
let http = require('http');
let fs = require('fs');
let server = http.createServer(function(req,res){
let body = [];
req.on('data',function(data){
body.push(data);
});
req.on('end',function(){
let result = Buffer.concat(body);
console.log(result.toString());
});
}).listen(8080,'127.0.0.1);
複製程式碼
1.8 querystring
querystring模組用來轉換URL字串和URL中的查詢字串
1.8.1 parse方法用來把字串轉換成物件
querystring.parse(str,[sep],[eq],[options]);
複製程式碼
1.8.2 stringify方法用來把物件轉換成字串
querystring.stringify(obj,[sep],[eq]);
複製程式碼
1.9 querystring
url.parse(urlStr,[parseQueryString]);
複製程式碼
- href 被轉換的原URL字串
- protocal 客戶端發出請求時使用的協議
- slashes 在協議與路徑之間是否使用了//分隔符
- host URL字串中的完整地址和埠號
- auth URL字串中的認證部分
- hostname URL字串中的完整地址
- port URL字串中的埠號
- pathname URL字串的路徑,不包含查詢字串
- search 查詢字串,包含?
- path 路徑,包含查詢字串
- query 查詢字串,不包含起始字串
?
- hash 雜湊字串,包含
#
1.10 傳送伺服器響應流
http.ServerResponse物件表示響應物件
1.10.1 writeHead
response.writeHead(statusCode,[reasonPhrase],[headers]);
複製程式碼
- content-type 內容型別
- location 將客戶端重定向到另外一個URL地址
- content-disposition 指定一個被下載的檔名
- content-length 伺服器響應內容的位元組數
- set-cookie 在客戶端建立Cookie
- content-encoding 指定伺服器響應內容的編碼方式
- cache-cache 開啟快取機制
- expires 用於制定快取過期時間
- etag 指定當伺服器響應內容沒有變化不重新下載資料
1.10.2 Header
設定、獲取和刪除Header
response.setHeader('Content-Type','text/html;charset=utf-8');
response.getHeader('Content-Type');
response.removeHeader('Content-Type');
response.headersSent 判斷響應頭是否已經傳送
複製程式碼
1.10.3 headersSent
判斷響應頭是否已經傳送
let http = require('http');
let server = http.createServer(function(req,res){
console.log(resopnse.headersSent?"響應頭已經傳送":"響應頭未傳送!");
res.writeHead(200,'ok);
console.log(resopnse.headersSent?"響應頭已經傳送":"響應頭未傳送!");
});
複製程式碼
1.10.4 sendDate
不傳送Date
res.sendDate = false;
複製程式碼
1.10.5 write
可以使用write方法傳送響應內容
response.write(chunk,[encoding]);
response.end([chunk],[encoding]);
複製程式碼
1.10.6 timeout
可以使用setTimeout方法設定響應讓超時時間,如果在指定時間內不響應,則觸發timeout事件
response.setTimeout(msecs,[callback]);
response.on('timeout',callback);
複製程式碼
1.10.7 close
在響應物件的end方法被呼叫之前,如果連線中斷,將觸發http.ServerResponse物件的close事件
response.on('close',callback);
複製程式碼
1.10.8 parser
net
onconnection
_http_server.js
連線監聽
connectionListenerInternal
socketOnData
onParserExecuteCommon
parserOnIncoming
複製程式碼
2. HTTP客戶端
2.1 向其他網站請求資料
let req = http.request(options,callback);
req.on('request',callback);
request.write(chunk,[encoding]);
request.end([chunk],[encoding]);
複製程式碼
- host 指定目標域名或主機名
- hostname 指定目標域名或主機名,如果和host都指定了,優先使用hostname
- port 指定目標伺服器的埠號
- localAddress 本地介面
- socketPath 指定Unix域埠
- method 指定HTTP請求的方式
- path 指定請求路徑和查詢字串
- headers 指定客戶端請求頭物件
- auth 指定認證部分
- agent 用於指定HTTP代理,在Node.js中,使用http.Agent類代表一個HTTP代理,預設使用keep-alive連線,同時使用http.Agent物件來實現所有的HTTP客戶端請求
let http = require('http');
let options = {
hostname: 'localhost',
port: 8080,
path: '/',
method: 'GET'
}
let req = http.request(options, function (res) {
console.log('狀態嗎:' + res.statusCode);
console.log('響應頭:' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('響應內容', chunk);
});
});
req.end();
複製程式碼
2.2 取消請求
可以使用abort方法來終止本次請求
req.abort();
複製程式碼
2.3 監聽error事件
如果請求過程中出錯了,會觸發error事件
request.on('error',function(err){});
複製程式碼
2.4 socket
建立連線過程中,為該連線分配埠時,觸發socket
事件
req.on('socket',function(socket){
socket.setTimeout(1000);
socket.on('timeout',function(){req.abort()});
});
複製程式碼
2.5 get
可以使用get方法向伺服器傳送資料
http.get(options,callback);
複製程式碼
2.6 addTrailers
可以使用response物件的addTrailers方法在伺服器響應尾部追加一個頭資訊
let http = require('http');
let path = require('path');
let crypto = require('crypto');
let server = http.createServer(function (req, res) {
res.writeHead(200, {
'Transfer-Encoding': 'chunked',
'Trailer': 'Content-MD5'
});
let rs = require('fs').createReadStream(path.join(__dirname, 'msg.txt'), {
highWaterMark: 2
});
let md5 = crypto.createHash('md5');
rs.on('data', function (data) {
console.log(data);
res.write(data);
md5.update(data);
});
rs.on('end', function () {
res.addTrailers({
'Content-MD5': md5.digest('hex')
});
res.end();
});
}).listen(8080);
複製程式碼
let http = require('http');
let options = {
hostname: 'localhost',
port: 8080,
path: '/',
method: 'GET'
}
let req = http.request(options, function (res) {
console.log('狀態嗎:' + res.statusCode);
console.log('響應頭:' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('響應內容', chunk);
});
res.on('end', function () {
console.log('trailer', res.trailers);
});
});
req.end();
複製程式碼
2.7 製作代理伺服器
let http = require('http');
let url = require('url');
let server = http.createServer(function (request, response) {
let {
path
} = url.parse(request.url);
let options = {
host: 'localhost',
port: 9090,
path: path,
headers: request.headers
}
let req = http.get(options, function (res) {
console.log(res);
response.writeHead(res.statusCode, res.headers);
res.pipe(response);
});
req.on('error', function (err) {
console.log(err);
});
request.pipe(req);
}).listen(8080);複製程式碼