NodeJS初學者教程:Node.js之HTTP

jcep6782 8年前發布 | 16K 次閱讀 HTTP Node.js Node.js 開發

來自: http://ourjs.com/detail/56dfb29588feaf2d031d2488

作者: swfbarhr 本文原載于其 Github

前言

在開始node.js(以后簡稱node)之前,我猶豫了好久:到底我第一篇用什么主題開始,是node的整體框架還是Hello world還是一堆廢話呢。最后我決定還是直接上API,簡單粗暴有效果,因為大家用node除了node有強大的社區之外,還因為node的API簡單易用,容易上手。OK,下面我們就開始node之旅。

HTTP

大部分的node使用者,都是用node來做Web API的,而HTTP模塊是提供Web API的基礎。為了支持所有的HTTP應用,node中的HTTTP模塊提供的API是偏向底層化的。利用HTTP模塊,我們可以簡單快速搭建一個Web Server。

引入HTTP模塊

在node 官方API 中,第一句話是這么說的:“To use the HTTP server and client one must require('http')”,如果想要使用HTTP的服務器端和客戶端的方法,首先第一步我們需要使用“require('http')”引入HTTP模塊。

var http = require('http');

我們引入了HTTP模塊,并且將結果賦值給了http變量,這樣http就擁有了HTTP模塊的所有方法和對象(關于requirejs的原理,與主題沒什么太大關系,就略過。但是記住,require的過程是一個同步的過程,而前端的引入define是一個異步過程)。

創建一個簡單的Web Server

在HTTP模塊中,node提供給我們一個createServer方法,來創建一個Web Server。代碼可以這樣寫:

var http = require('http');
var server = http.createServer();

server.on('request', function(request, response) { console.log('有人請求了服務器!');

response.writeHead(200, { 'Content-Type': 'text/plain' }); response.write('OK'); response.end(); });

server.listen(88, function() { console.log('服務器已經開始監聽88端口'); });</pre>

上面的代碼:

  • 我們首先用http.createServer(從express4.X時代進入的同學可能有點陌生,express在4.X后把該方法封裝到了其內部,但是我們在創建HTTPS連接時,還是要用到此方法)函數創建了一個服務器對象。

  • 然后監聽了該對象的“request”事件(了解過node的同學應該知道,node是事件驅動的,一般事件觸發和事件接收是成對出現的),這邊我們定義接收事件。也就是說,如果當前服務器對象監聽的端口一旦被請求,那么就會觸發該事件。“request”的回調中,我們首先調用了response.writeHead方法:該方法的第一個參數表示HTTP的響應狀態(200)表示一切正常;第二個參數是“Content-Type”,表示我響應給客戶端的內容類型。然后我們調用了response.write方法,寫入我們需要傳遞給客戶端的內容。最后一步我們調用了response.end,表示此次請求已處理完成。

  • 最后我們調用了server.listen函數,此函數有兩個參數,第一個參數表示我們需要監聽的端口,第二個參數是回調函數(其實是listening事件),當監聽開啟后立刻觸發。所以當我們用node命令來啟動當前的js文件后,在cmd窗口會馬上出現“服務器已經開始監聽88端口”的字樣,表明服務器正常且已經開始監聽88端口。

當我們請求了服務器的88端口后,服務器會響應給我們“OK”字符串。到此我們的簡單Web Server已經搭建完成,但是此時我們的代碼還不具備任何業務能力,但是我們只要把代碼稍稍修改下,就可以入眼了:

var url = require('url');
var http = require('http');
var server = http.createServer();

function bizLogic(url) {

if (url.path.toLowerCase() === '/login') { return { msg: '登錄成功!' } } else if (url.path.toLowerCase() === '/user') { return { msg: [{ name: '小明', class: '一年級1班' }, { name: '小紅', class: '一年級3班' }] } } else { return { msg: 404 } } }

server.on('request', function(request, response) {

if ('url' in request) { response.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });

response.write(JSON.stringify(bizLogic(url.parse(request.url))), 'utf8');

} else { response.writeHead(404, { 'Content-Type': 'application/json; charset=utf-8' });

response.write('找不到頁面');

}

response.end(); });

server.listen(88, function() { console.log('服務器已經開始監聽88端口'); });</pre>

  • 首先我們引入了一個新的模塊:“url”。這個模塊主要幫助我們將整理請求url中的信息即url.parse方法(如果有興趣,你可以去研究下url的所有API,其實就幾個)。url.parse轉換完成之后,url參數信息就變成這樣了:
  • </ul>

    {
        protocol: null,
        slashes: null,
        auth: null,
        host: null,
        port: null,
        hostname: null,
        hash: null,
        search: null,
        query: null,
        pathname: '/login',
        path: '/login',
        href: '/login'
    }

    這里我們取了我們需要的參數:path,簡單的根據path來判斷接口。然后響應客戶端不同的內容。

    • 如果我們直接“response.write(bizLogic(url.parse(request.url)), 'utf8');”系統就會報錯,response.write第一個參數必須是string或者Buffer,所以我們在這里將object轉換成了string,然后接著write。

    • 最后我們直接結束連接(response.end)。

    好了,一個簡單的業務已經處理完成了,但是實際開過過程沒有那么簡單:HTTP方法有“GET”、“POST”、“PUT”等等。這也是要我們來處理的,所以如果我們用node來做Web API的話,一般會選擇第三方的Web框架如:express、koa、restify等等(好吧,這是后話了,以后有機會我會去研究下他們各自的源碼給大家分享)。

    http.request

    上面講了那么多,其實都是在將HTTP Server的內容,既然node那么強大,當然除了可以作為HTTP Server之外,也可以做HTTP Client。現在就以我們剛剛建立的服務端為服務器,利用http.request來請求剛剛的服務器,看看會發生什么事情。

    var http = require('http');

    var option, req;

    option = { host: '127.0.0.1', port: 88, path: '/login' };

    req = http.request(option, function(res){

    if(res.statusCode === 200) { console.log('ok'); }

    res.on('data', function(chunk){ console.log('the result is ', chunk.toString()); }); });

    req.on('error', function(error){ console.log('something is wrong:', error.message); });

    req.end();</pre>

    • 首先我們當然要引入http模塊,之后又定義了option和req對象。option是我們一會需要請求服務器的一些參數,req是請求對象用于接收request返回的結果(并不是請求的結果)

    • option參數是一個對象,使我們對此次請求設置的參數,包括:我們要請求的主機地址(host,注意此處不需要“ http://”)、請求的請求的端口號(port)、請求的路由及參數(path

    • 調用http.request請求,第一個參數就是我們剛剛設置的option,第二個參數是回調函數(用于返回我們請求的結果)

    • 回調函數有一個參數,這個參數是http.IncomingMessage的實例。字面意思就是“進來的消息”,也就是請求收到的響應結果對象。http.IncomingMessage實現了可讀流接口,也就是說我們的“data”事件被觸發時,回調函數中的結果是Buffer(關于Buffer我以后會詳細解釋---另一篇博客)對象,所以我在打印的時候調用了Bufer對象的toString方法把Buffer對象轉換成字符串打印出來。

    • 最后我們監聽了req的錯誤事件(在node中,我們如果出錯不定義error事件的話,程序就會直接把錯誤拋出,如果沒有做錯誤捕獲的話,node程序就會崩掉),用于記錄錯誤信息。最后我們關閉了請求。

    • </ul>

      經過這幾個簡單地步驟,我們此次請求就完成了,如果服務端沒有錯誤的話,使用node命令運行我們剛剛寫好的客戶端代碼,在cmd窗口先會打印“ok”,然后帶打印“the result is {"msg":"登錄成功!"}”。一旦請求出錯,就會直接出發我們的“error”事件。當然如果不想使用原生的HTTP模塊的話,你也可以使用第三方的包: requestsuperagent 等都是非常優秀且方便的第三方包。(原生的HTTP模塊可能會遇到各種奇葩的問題,使用第三方包的話嗎,坑會少一些)。

      其他方法和事件

      • http.get是http.request的“GET”方法的方便版本,只能執行“GET”操作。

      • http.ClientRequest的“connection”事件,當TCP(HTTP其實也是TCP)的連接通道建立之后觸發的事件。

      • http.ClientRequest的“close”事件,當服務端關閉連接時觸發。

      • http.ServerResponse的setTimeout方法,設置響應超時。如果沒有設置的話,只能等待socket或服務器超時。(還有很多方法和事件。就不一一列舉了。)

      總結

      在node v0.10.x時代,HTTP模塊的穩定系數就已經是3了(一般node的API有4個級別,分別是:Deprecated-0、Experimental-1、Stable-2、Locked-3).所以說HTTP模塊的API非常基礎和穩定的。我們使用HTTP模塊時,可以很放心的使用其方法和事件,不必擔心版本兼容問題。需要提到的是,學習node的最好最捷徑的方法就是學會讀官方API,官方API雖然是英文的,但是里面的解釋和英文單詞都是很戳中要點和易于理解的。另外本文也會在我的 博客 上同步更新,歡迎訪問。

      </div>

 本文由用戶 jcep6782 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!