前言
Node.js開發的目的就是為了用JavaScript編寫Web服務器程序。因為JavaScript實際上已經統治了瀏覽器端的腳本,其優勢就是有世界上數量最多的前端開發人員。如果已經掌握了JavaScript前端開發,再學習一下如何將JavaScript應用在后端開發,就是名副其實的全棧了。
HTTP協議
要理解Web服務器程序的工作原理,首先,我們要對HTTP協議有基本的了解。如果你對HTTP協議不太熟悉,先看一看HTTP協議簡介。
HTTP服務器
要開發HTTP服務器程序,從頭處理TCP連接,解析HTTP是不現實的。這些工作實際上已經由Node.js自帶的http模塊完成了。應用程序并不直接和HTTP協議打交道,而是操作http模塊提供的request和response對象。
request對象封裝了HTTP請求,我們調用request對象的屬性和方法就可以拿到所有HTTP請求的信息;
response對象封裝了HTTP響應,我們操作response對象的方法,就可以把HTTP響應返回給瀏覽器。
用Node.js實現一個HTTP服務器程序非常簡單。我們來實現一個最簡單的Web程序hello.js,它對于所有請求,都返回Hello world!:
1
2
3
4
5
6
7
8
9
10
11
|
'use strict' ; var http = require( 'http' ); // 導入http模塊 // 創建http server,并傳入回調函數。回調函數接收request和response對象 var server = http.createServer( function (request, response){ console.log(request.method + ': ' + request.url); // 獲得HTTP請求的method和url: response.writeHead(200, { 'Content-Type' : 'text/html' }); // 將HTTP響應200寫入response, 同時設置Content-Type: text/html response.end( '<h1>Hello world!</h1>' ); }); // 將HTTP響應的HTML內容寫入response server.listen(8080); // 讓服務器監聽8080端口 console.log( 'Server is running at http://127.0.0.1:8080/' ); |
在命令提示符下運行該程序,可以看到以下輸出:
$ node hello.js Server is running at http://127.0.0.1:8080/
不要關閉命令提示符,直接打開瀏覽器輸入http://localhost:8080,即可看到服務器響應的內容:
同時,在命令提示符窗口,可以看到程序打印的請求信息:
GET: /
GET: /favicon.ico
這就是我們編寫的第一個HTTP服務器程序!
文件服務器
讓我們繼續擴展一下上面的Web程序。我們可以設定一個目錄,然后讓Web程序變成一個文件服務器。要實現這一點,我們只需要解析request.url中的路徑,然后在本地找到對應的文件,把文件內容發送出去就可以了。
解析URL需要用到Node.js提供的url模塊,它使用起來非常簡單,通過parse()將一個字符串解析為一個Url對象:
1
2
3
4
|
'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' }
處理本地文件目錄需要使用Node.js提供的path模塊,它可以方便地構造目錄:
1
2
3
4
|
'use strict' ; var path = require( 'path' ); var workDir = path.resolve( '.' ); // 解析當前目錄('/Users/michael') var filePath = path.join(workDir, 'pub' , 'index.html' ); // 組合完整的文件路徑:當前目錄+'pub'+'index.html'('/Users/michael/pub/index.html') |
使用path模塊可以正確處理操作系統相關的文件路徑。在Windows系統下,返回的路徑類似于C:\Users\michael\static\index.html,這樣,我們就不關心怎么拼接路徑了。
最后,我們實現一個文件服務器file_server.js:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
'use strict' ; var fs = require( 'fs' ),url = require( 'url' ),path = require( 'path' ),http = require( 'http' ); var root = path.resolve(process.argv[2] || '.' ); // 從命令行參數獲取root目錄,默認是當前目錄 console.log( 'Static root dir: ' + root); var server = http.createServer( function (request, response){ // 創建服務器 var pathname = url.parse(request.url).pathname; // 獲得URL的path,類似 '/css/bootstrap.css' var filepath = path.join(root, pathname); // 獲得對應的本地文件路徑,類似 '/srv/www/css/bootstrap.css' fs.stat(filepath, function (err, stats) { if (!err && stats.isFile()) { // 獲取文件狀態 console.log( '200 ' + request.url); // 沒有出錯并且文件存在 response.writeHead(200); // 發送200響應 // 將文件流導向response: fs.createReadStream(filepath).pipe(response); } else { console.log( '404 ' + request.url); // 出錯了或者文件不存在 response.writeHead(404); response.end( '404 Not Found' ); } }); }); // 發送404響應 server.listen(8080); console.log( 'Server is running at http://127.0.0.1:8080/' ); |
沒有必要手動讀取文件內容。由于response對象本身是一個Writable Stream,直接用pipe()方法就實現了自動讀取文件內容并輸出到HTTP響應。
在命令行運行node file_server.js /path/to/dir,把/path/to/dir改成你本地的一個有效的目錄,然后在瀏覽器中輸入http://localhost:8080/index.html:
只要當前目錄下存在文件index.html,服務器就可以把文件內容發送給瀏覽器。觀察控制臺輸出:
200 /index.html
200 /css/uikit.min.css
200 /js/jquery.min.js
200 /fonts/fontawesome-webfont.woff2
第一個請求是瀏覽器請求index.html頁面,后續請求是瀏覽器解析HTML后發送的其它資源請求。
練習
在瀏覽器輸入http://localhost:8080/時,會返回404,原因是程序識別出HTTP請求的不是文件,而是目錄。請修改file_server.js;如果遇到請求的路徑是目錄,則自動在目錄下依次搜索index.html、default.html,如果找到了,就返回HTML文件的內容。
參考源碼
http服務器代碼(含靜態網站)
https://github.com/michaelliao/learn-javascript/tree/master/samples/node/http
以上就是Node.js之http模塊的用法的詳細內容,更多關于Node.js的資料請關注服務器之家其它相關文章!
原文鏈接:https://blog.csdn.net/weixin_39214481/article/details/82778634