您好,登錄后才能下訂單哦!
這篇文章主要介紹“怎么使用Node.js開發靜態資源服務器”,在日常操作中,相信很多人在怎么使用Node.js開發靜態資源服務器問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么使用Node.js開發靜態資源服務器”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
Node.js
經過這么多年的發展,已經有了很多很優秀的基礎框架或類庫,像express.js
、Koa.js
、egg.js
等,它們都是基于原生的Node.js
來實現的,而我們之所以不選擇用這些框架,其實就是希望大家能夠了解前面這幾種框架是如何實現一個基礎的靜態資源服務的,只有當我們了解了這其中的知識點,再使用這些框架時才會更加得心應手,下面我們一起看一下這個基礎的靜態資源服務該如何開發吧!
首先,我們要了解的是,既然是要開發靜態資源服務,那么什么是靜態資源服務呢?簡單來說就是可以靜態訪問的一個資源服務器,而這些靜態資源包括但不限于類似html
、css
、js
以及一些圖片資源,音視頻等等。我們能通過網絡直接訪問這些內容,就是因為它們通過靜態資源服務器將這些內容掛載在網上。
我們首先要做的就是創建一個服務,在Node
中我們通過http
模塊來創建一個服務,http
是Node
中的一個基礎的API
,相關的內容可以查閱官方文檔,然后我們需要讀取本地的資源,那么就需要用到另外一個模塊fs
。fs
模塊能夠操作本地的資源文件,具體的內容也可以通過官網的文檔進行查看,下面我們一起來看一下相關的代碼,代碼如下:
const fs = require('fs'); const http = require('http'); http.createServer((req, res) => { fs.readFile(__dirname + req.url, (err, data) => { if (err) { res.writeHead(404, { 'Content-Type': 'text/html' }); res.end('404: File not found'); } else { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(data); } }); }).listen(8000);
在上述的代碼中,我們首先通過http.createServer
創建了一個服務器,并且通過listen(8000)
來監聽了8000端口的服務,這樣我們就可以直接在瀏覽器中通過訪問localhost:8000
來進行訪問;在這個服務的內部,我們通過fs.readFile
方法來讀取文件,因為我們沒有指定讀取的具體內容,而是通過獲取請求信息來判斷我們要展示給用戶看到的內容,所以最終會在頁面中展示404
,如下圖所示:
上面的代碼已經簡單了實現了一個靜態資源服務了,但是代碼看起來就比較零散,下面我們一起來對這個代碼進行改造,通過模塊化的思想對代碼進行升級,這樣不至于讓我們的代碼看起來像面條代碼。
首先,我們讀取的文件地址可能跟我們的這個文件服務不在一個目錄中,為了解決問題問題,我們需要修改我們的文件目錄,而關于目錄的相關信息,就不得不用到Node
中另外一個很重要的模塊path
了。通過path
模塊,我們能夠解析不同目錄中的內容,一起來看一下修改后的代碼吧,如下:
const fs = require('fs'); const path = require('path'); const directoryName = './public'; const requestUrl = 'index.html'; const filePath = path.join(directoryName, requestUrl); fs.readFile(filePath, (err, data) => { // ... });
我們通過path
將靜態資源的根目錄拼接在一起,這樣當我們使用fs.readFile
來讀取這個文件時,不至于因為路徑錯誤而讀取不到正確的內容。
接下來我們需要考慮的就是安全性的問題了,因為我們不希望用戶能夠在未授權的情況隨意訪問我們服務器中的任意資源,目前并不是不能訪問除了指定的目錄外的文件,這就是一個安全性的問題。為了解決這個問題,我們可以通過path
模塊來檢測用戶請求的文件是否是可以訪問的,下面一起看看我們對上述代碼的改造,如下:
const path = require('path'); const directoryName = './public'; const root = path.normalize(path.resolve(directoryName)); const requestUrl = 'index.html'; const filePath = path.join(root, fileName); const isPathUnderRoot = path .normalize(path.resolve(filePath)) .startsWith(root);
上述代碼中,我們通過path.normalize
來檢測這個文件地址是否包含在根路徑中,這樣就能確保用戶只能訪問到我們允許訪問的地址。同樣的,我們還可以通過檢查文件的類型來確保用戶無法訪問到一些敏感的文件。
為此,我們需要指定能夠訪問的文件類型的數組或對象,只有當用戶訪問的文件在這個數組或者對象中,才能展示給用戶看到,因此我們還需要用到path
模塊來檢查文件的后綴名,修改后代碼如下:
const path = require('path'); const types = ['html', 'css', 'js', 'json']; const requestUrl = 'index.html'; const extension = path.extname(requestUrl).slice(1); const isTypeSupported = types.includes(extension);
我們定義了一個文件類型的數組,其中就包含了用戶可以訪問的資源類型,然后我們通過path.extname
來檢測用戶請求的文件的后綴,只有在這個類型文件的數組包含的類型,才會展示給用戶進行查看。
當然,當我們訪問html
的時候,我們一般都不會也不需要在瀏覽器中輸入xxx.html
這樣的后綴,因此我們還需要對html
這樣的后綴做省略,讓用戶可以直接通過網址就能訪問正確的頁碼,而不需要添加.html
。下面我們一起看一下改造后的代碼,如下:
const fs = require('fs'); const path = require('path'); const directoryName = './public'; const root = path.normalize(path.resolve(directoryName)); const extension = path.extname(req.url).slice(1); let fileName = requestUrl; if (requestUrl === '/') { fileName = 'index.html'; } else if (!extension) { try { fs.accessSync(path.join(root, requestUrl + '.html'), fs.constants.F_OK); fileName = requestUrl + '.html'; } catch (e) { fileName = path.join(requestUrl, 'index.html'); } }
上述的代碼中,我們通過判斷用戶訪問的文件類型是否包含在前面的數組中,當用戶訪問的類型不包含時,我們通過fs.accessSync
來測試用戶訪問的文件是否是允許訪問的,如果允許訪問則直接返回一個.html
的文件,如果用戶訪問的地址是不允許訪問的,則直接返回index.html
。
最后,當我們將前面所有的內容都完成后,我們可以將這些內容都整合在一起,下面我們一起來看一下最終完成的這個靜態資源服務的完整代碼吧,如下:
const fs = require('fs'); const http = require('http'); const path = require('path'); // 靜態資源服務器地址 const port = 8000; // 靜態資源文件夾 const directoryName = './public'; // 允許訪問的文件類型 const types = { html: 'text/html', css: 'text/css', js: 'application/javascript', png: 'image/png', jpg: 'image/jpeg', jpeg: 'image/jpeg', gif: 'image/gif', json: 'application/json', xml: 'application/xml', }; // 靜態資源文件根路徑 const root = path.normalize(path.resolve(directoryName)); // 創建靜態資源服務器 const server = http.createServer((req, res) => { // 獲取訪問的文件類型 const extension = path.extname(req.url).slice(1); // 文件類型后綴 const type = extension ? types[extension] : types.html; // 是否支持的文件類型 const supportedExtension = Boolean(type); // 如果這個文件類型不允許訪問,則直接返回404 if (!supportedExtension) { res.writeHead(404, { 'Content-Type': 'text/html' }); res.end('404: File not found'); return; } // 通過url獲取訪問的文件名稱 let fileName = req.url; // 如果訪問的路徑是 / if (req.url === '/') { // 則文件名是 index.html fileName = 'index.html'; } else if (!extension) { try { // 檢測文件是否允許訪問 fs.accessSync(path.join(root, req.url + '.html'), fs.constants.F_OK); // 當允許訪問時,則返回對應的頁面 fileName = req.url + '.html'; } catch (e) { // 否則直接返回 index.html fileName = path.join(req.url, 'index.html'); } } const filePath = path.join(root, fileName); const isPathUnderRoot = path.normalize(path.resolve(filePath)).startsWith(root); if (!isPathUnderRoot) { res.writeHead(404, { 'Content-Type': 'text/html' }); res.end('404: File not found'); return; } fs.readFile(filePath, (err, data) => { if (err) { res.writeHead(404, { 'Content-Type': 'text/html' }); res.end('404: File not found'); } else { res.writeHead(200, { 'Content-Type': type }); res.end(data); } }); }); server.listen(port, () => { console.log(`Server is listening on port ${port}`); });
最終我們通過不到100行的代碼就實現了這個靜態資源服務,我們可以看一下具體的運行效果。
當我們訪問首頁時,就直接展示默認的index.html
中的文件,如果我們訪問的內容不允許訪問,則直接顯示404
,如下所示:
到此,關于“怎么使用Node.js開發靜態資源服務器”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。