NodeJS學習筆記 (7)網絡服務-http-client(ok)


原文:https://github.com/chyingp/nodejs-learning-guide

 

自己敲代碼:

 

ClientRequest概覽

當你調用 http.request(options) 時,會返回 ClientRequest實例,主要用來創建HTTP客戶端請求。

在前面的章節里,已經對http模塊的的其他方面進行了不少介紹,如http.Server、http.ServerResponse、http.IncomingMessage。

有了前面的基礎,詳細本文不難理解,本文更多的以例子為主。

 

簡單的GET請求

下面構造了個GET請求,訪問 http://id.qq.com/ ,並將返回的網頁內容打印在控制台下。

var http = require('http'); var options = { protocol: 'http:', hostname: 'id.qq.com', port: '80', path: '/', method: 'GET' }; var client = http.request(options, function(res){ var data = ''; res.setEncoding('utf8'); res.on('data', function(chunk){ data += chunk; }); res.on('end', function(){ console.log(data); }); }); client.end();

當然,也可以用便捷方法 http.get(options) 進行重寫

var http = require('http'); http.get('http://id.qq.com/', function(res){ var data = ''; res.setEncoding('utf8'); res.on('data', function(chunk){ data += chunk; }); res.on('end', function(){ console.log(data); }); });



簡單的post請求

在下面例子中,首先創建了個http server,負責將客戶端發送過來的數據回傳。

接着,創建客戶端POST請求,向服務端發送數據。需要注意的點有:

  1. method 指定為 POST。
  2. headers 里聲明了 content-type 為 application/x-www-form-urlencoded。
  3. 數據發送前,用 querystring.stringify(obj) 對傳輸的對象進行了格式化。
var http = require('http'); var querystring = require('querystring'); var createClientPostRequest = function(){ var options = { method: 'POST', protocol: 'http:', hostname: '127.0.0.1', port: '3000', path: '/post', headers: { "connection": "keep-alive", "content-type": "application/x-www-form-urlencoded" } }; // 發送給服務端的數據 var postBody = { nick: 'chyingp' }; // 創建客戶端請求 var client = http.request(options, function(res){ // 最終輸出:Server got client data: nick=chyingp res.pipe(process.stdout); }); // 發送的報文主體,記得先用 querystring.stringify() 處理下 client.write( querystring.stringify(postBody) ); client.end(); }; // 服務端程序,只是負責回傳客戶端數據 var server = http.createServer(function(req, res){ res.write('Server got client data: '); req.pipe(res); }); server.listen(3000, createClientPostRequest);

各種事件

在官方文檔里,http.RequestClient相關的事件共有7個。跟HTTP協議密切相關的有3個,分別是 connect、continue、upgrade,其他4個分別是 abort、aborted、socket、response。

  • 其他:abort、aborted、socket、response
  • 與HTTP協議相關:connect、continue、upgrade

跟HTTP協議相關的會相對復雜些,因為涉及HTTP協議的設計細節。其他3個相對簡單。下面分別進行簡單的介紹。

response事件

最容易理解的一個,當收到來自服務端的響應時觸發,其實跟 http.get(url, cbk) 中的回調是一樣的,看下程序運行的打印信息就知道。

var http = require('http'); var url = 'http://id.qq.com/'; var client = http.get(url, function(res){ console.log('1. response event'); }); client.on('response', function(res){ console.log('2. response event'); }); client.end();

打印信息:

1. response event
2. response event

socket事件

當給client分配socket的時候觸發,如果熟悉net模塊對這個事件應該不陌生。大部分時候並不需要關注這個事件,雖然內部其實挺復雜的。

abort/aborted 事件

這兩個事件看着非常像,都是請求中斷時觸發,差異在於中斷的發起方:

  • abort:客戶端主動中斷請求(第一次調用 client.abort() 時觸發)
  • aborted:服務端主動中斷請求,且請求已經中斷時觸發。

continue事件

當收到服務端的響應 100 Continue 時觸發。熟悉HTTP協議的同學應該對 100 Continue 有所了解。當客戶端向服務端發送首部 Expect: 100-continue ,服務端經過一定的校驗后,決定對客戶端的后續請求放行,於是返回返回 100 Continue,知會客戶端,可以繼續發送數據。(request body)

upgrade事件

同樣是跟HTTP協議密切相關。當客戶端向客戶端發起請求時,可以在請求首部里聲明 'Connection': 'Upgrade' ,以此要求服務端,將當前連接升級到新的協議。如果服務器同意,那么就升級協議繼續通信。這里不打算展開太多細節,直接上官方文檔的代碼

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); }); });

其他

除了上面講解到的屬性、方法、事件外,還有下面方法沒有講到。並不是它們不重要,篇幅有限,后面再展開。

  • client.abort():中斷請求;
  • client.setTimeout(timeout):請求超時設置;
  • client.flushHeaders() 及早將請求首部發送出去;
  • client.setSocketKeepAlive():當內部分配 socket 並連接上時,就會內部調用 socket.keepAlive();
  • client.setNoDelay([noDelay]):當內部分配 socket 並連接上時,就會內部調用 socket.setNoDelay();

參考鏈接

upgrade機制: https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism

官方文檔: https://nodejs.org/api/http.html#http_class_http_clientrequest

nodejs源碼: https://github.com/nodejs/node/blob/master/lib/_http_client.js


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM