亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Node.js開發(fā)靜態(tài)資源服務(wù)器

 更新時(shí)間:2022年08月08日 16:54:20   作者:愛吃魚的桶哥Z  
這篇文章主要為大家介紹了Node.js開發(fā)靜態(tài)資源服務(wù)器示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

正文

在09年Node.js出來后,讓前端開發(fā)人員的開發(fā)路線變的不再那么單調(diào),經(jīng)過這么多年的發(fā)展,我們的開發(fā)基本已經(jīng)離不開Node.js,不管是用作于工具類的開發(fā),還是做完服務(wù)端的中間層,Node.js都占據(jù)了非常重要的地位,今天我們就一起通過原生的js+Node來實(shí)現(xiàn)一個(gè)簡單的靜態(tài)資源服務(wù),如果你還不了解這方面的知識(shí),那就跟我一起來學(xué)習(xí)吧!

靜態(tài)資源服務(wù)器

Node.js經(jīng)過這么多年的發(fā)展,已經(jīng)有了很多很優(yōu)秀的基礎(chǔ)框架或類庫,像express.js、Koa.js、egg.js等,它們都是基于原生的Node.js來實(shí)現(xiàn)的,而我們之所以不選擇用這些框架,其實(shí)就是希望大家能夠了解前面這幾種框架是如何實(shí)現(xiàn)一個(gè)基礎(chǔ)的靜態(tài)資源服務(wù)的,只有當(dāng)我們了解了這其中的知識(shí)點(diǎn),再使用這些框架時(shí)才會(huì)更加得心應(yīng)手,下面我們一起看一下這個(gè)基礎(chǔ)的靜態(tài)資源服務(wù)該如何開發(fā)吧!

首先,我們要了解的是,既然是要開發(fā)靜態(tài)資源服務(wù),那么什么是靜態(tài)資源服務(wù)呢?簡單來說就是可以靜態(tài)訪問的一個(gè)資源服務(wù)器,而這些靜態(tài)資源包括但不限于類似html、css、js以及一些圖片資源,音視頻等等。我們能通過網(wǎng)絡(luò)直接訪問這些內(nèi)容,就是因?yàn)樗鼈兺ㄟ^靜態(tài)資源服務(wù)器將這些內(nèi)容掛載在網(wǎng)上。

我們首先要做的就是創(chuàng)建一個(gè)服務(wù),在Node中我們通過http模塊來創(chuàng)建一個(gè)服務(wù),httpNode中的一個(gè)基礎(chǔ)的API,相關(guān)的內(nèi)容可以查閱官方文檔,然后我們需要讀取本地的資源,那么就需要用到另外一個(gè)模塊fsfs模塊能夠操作本地的資源文件,具體的內(nèi)容也可以通過官網(wǎng)的文檔進(jìn)行查看,下面我們一起來看一下相關(guān)的代碼,代碼如下:

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創(chuàng)建了一個(gè)服務(wù)器,并且通過listen(8000)來監(jiān)聽了8000端口的服務(wù),這樣我們就可以直接在瀏覽器中通過訪問localhost:8000來進(jìn)行訪問;在這個(gè)服務(wù)的內(nèi)部,我們通過fs.readFile方法來讀取文件,因?yàn)槲覀儧]有指定讀取的具體內(nèi)容,而是通過獲取請(qǐng)求信息來判斷我們要展示給用戶看到的內(nèi)容,所以最終會(huì)在頁面中展示404,如下圖所示:

上面的代碼已經(jīng)簡單了實(shí)現(xiàn)了一個(gè)靜態(tài)資源服務(wù)了,但是代碼看起來就比較零散,下面我們一起來對(duì)這個(gè)代碼進(jìn)行改造,通過模塊化的思想對(duì)代碼進(jìn)行升級(jí),這樣不至于讓我們的代碼看起來像面條代碼。

模塊化

首先,我們讀取的文件地址可能跟我們的這個(gè)文件服務(wù)不在一個(gè)目錄中,為了解決問題問題,我們需要修改我們的文件目錄,而關(guān)于目錄的相關(guān)信息,就不得不用到Node中另外一個(gè)很重要的模塊path了。通過path模塊,我們能夠解析不同目錄中的內(nèi)容,一起來看一下修改后的代碼吧,如下:

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將靜態(tài)資源的根目錄拼接在一起,這樣當(dāng)我們使用fs.readFile來讀取這個(gè)文件時(shí),不至于因?yàn)槁窂藉e(cuò)誤而讀取不到正確的內(nèi)容。

接下來我們需要考慮的就是安全性的問題了,因?yàn)槲覀儾幌M脩裟軌蛟谖词跈?quán)的情況隨意訪問我們服務(wù)器中的任意資源,目前并不是不能訪問除了指定的目錄外的文件,這就是一個(gè)安全性的問題。為了解決這個(gè)問題,我們可以通過path模塊來檢測(cè)用戶請(qǐng)求的文件是否是可以訪問的,下面一起看看我們對(duì)上述代碼的改造,如下:

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來檢測(cè)這個(gè)文件地址是否包含在根路徑中,這樣就能確保用戶只能訪問到我們?cè)试S訪問的地址。同樣的,我們還可以通過檢查文件的類型來確保用戶無法訪問到一些敏感的文件。

為此,我們需要指定能夠訪問的文件類型的數(shù)組或?qū)ο?,只有?dāng)用戶訪問的文件在這個(gè)數(shù)組或者對(duì)象中,才能展示給用戶看到,因此我們還需要用到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);

我們定義了一個(gè)文件類型的數(shù)組,其中就包含了用戶可以訪問的資源類型,然后我們通過path.extname來檢測(cè)用戶請(qǐng)求的文件的后綴,只有在這個(gè)類型文件的數(shù)組包含的類型,才會(huì)展示給用戶進(jìn)行查看。

當(dāng)然,當(dāng)我們?cè)L問html的時(shí)候,我們一般都不會(huì)也不需要在瀏覽器中輸入xxx.html這樣的后綴,因此我們還需要對(duì)html這樣的后綴做省略,讓用戶可以直接通過網(wǎng)址就能訪問正確的頁碼,而不需要添加.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');
    }
}

上述的代碼中,我們通過判斷用戶訪問的文件類型是否包含在前面的數(shù)組中,當(dāng)用戶訪問的類型不包含時(shí),我們通過fs.accessSync來測(cè)試用戶訪問的文件是否是允許訪問的,如果允許訪問則直接返回一個(gè).html的文件,如果用戶訪問的地址是不允許訪問的,則直接返回index.html。

最后,當(dāng)我們將前面所有的內(nèi)容都完成后,我們可以將這些內(nèi)容都整合在一起,下面我們一起來看一下最終完成的這個(gè)靜態(tài)資源服務(wù)的完整代碼吧,如下:

const fs = require('fs');
const http = require('http');
const path = require('path');
// 靜態(tài)資源服務(wù)器地址
const port = 8000;
// 靜態(tài)資源文件夾
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',
};
// 靜態(tài)資源文件根路徑
const root = path.normalize(path.resolve(directoryName));
// 創(chuàng)建靜態(tài)資源服務(wù)器
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);
    // 如果這個(gè)文件類型不允許訪問,則直接返回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 {
            // 檢測(cè)文件是否允許訪問
            fs.accessSync(path.join(root, req.url + '.html'), fs.constants.F_OK);
            // 當(dāng)允許訪問時(shí),則返回對(duì)應(yīng)的頁面
            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行的代碼就實(shí)現(xiàn)了這個(gè)靜態(tài)資源服務(wù),我們可以看一下具體的運(yùn)行效果。

當(dāng)我們?cè)L問首頁時(shí),就直接展示默認(rèn)的index.html中的文件,如果我們?cè)L問的內(nèi)容不允許訪問,則直接顯示404,如下所示:

最后

我們只通過Node.js中一些簡單的API就開發(fā)了一個(gè)基礎(chǔ)的靜態(tài)資源服務(wù)器,也讓大家了解了一些Node.js相關(guān)的基礎(chǔ)操作,了解這些基礎(chǔ)的操作不僅有利于提高我們自身的知識(shí)儲(chǔ)備,也更有利于我們?cè)趯?shí)際開發(fā)中少踩一些坑。

以上就是Node.js開發(fā)靜態(tài)資源服務(wù)器的詳細(xì)內(nèi)容,更多關(guān)于Node.js靜態(tài)資源服務(wù)器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • node.js中的http.response.setHeader方法使用說明

    node.js中的http.response.setHeader方法使用說明

    這篇文章主要介紹了node.js中的http.response.setHeader方法使用說明,本文介紹了http.response.setHeader的方法說明、語法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下
    2014-12-12
  • node.js在Linux下執(zhí)行shell命令、.sh腳本的問題

    node.js在Linux下執(zhí)行shell命令、.sh腳本的問題

    很多時(shí)候需要多個(gè)命令來完成一項(xiàng)工作,而這個(gè)工作又常常是重復(fù)的,這個(gè)時(shí)候我們自然會(huì)想到將這些命令寫成sh腳本,下次執(zhí)行下這個(gè)腳本一切就都搞定了,下面就是發(fā)布代碼的一個(gè)腳本示例
    2022-01-01
  • 關(guān)于Node.js的events.EventEmitter用法介紹

    關(guān)于Node.js的events.EventEmitter用法介紹

    本篇文章主要介紹了關(guān)于Node.js的events.EventEmitter用法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-04-04
  • 利用Node.js如何實(shí)現(xiàn)文件循環(huán)覆寫

    利用Node.js如何實(shí)現(xiàn)文件循環(huán)覆寫

    這篇文章主要給大家介紹了關(guān)于利用Node.js如何實(shí)現(xiàn)文件循環(huán)覆寫的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Node.js具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Node.js的基本應(yīng)用你知道多少

    Node.js的基本應(yīng)用你知道多少

    這篇文章主要為大家詳細(xì)介紹了Node.js的基本應(yīng)用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-02-02
  • 從零開始學(xué)習(xí)Node.js系列教程五:服務(wù)器監(jiān)聽方法示例

    從零開始學(xué)習(xí)Node.js系列教程五:服務(wù)器監(jiān)聽方法示例

    這篇文章主要介紹了Node.js服務(wù)器監(jiān)聽方法,結(jié)合實(shí)例形式分析了nodejs事件監(jiān)聽相關(guān)操作技巧,需要的朋友可以參考下
    2017-04-04
  • 通過nodejs 服務(wù)器讀取HTML文件渲染到頁面的方法

    通過nodejs 服務(wù)器讀取HTML文件渲染到頁面的方法

    今天小編就為大家分享一篇通過nodejs 服務(wù)器讀取HTML文件渲染到頁面的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • node中IO以及定時(shí)器優(yōu)先級(jí)詳解

    node中IO以及定時(shí)器優(yōu)先級(jí)詳解

    這篇文章主要給大家介紹了關(guān)于node中IO以及定時(shí)器優(yōu)先級(jí)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用node具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • 基于NodeJS的前后端分離的思考與實(shí)踐(五)多終端適配

    基于NodeJS的前后端分離的思考與實(shí)踐(五)多終端適配

    對(duì)比基于瀏覽器的響應(yīng)式設(shè)計(jì)方案,因?yàn)榻^大部分終端探測(cè)和渲染邏輯遷移到了服務(wù)端,所以在 NodeJS 層進(jìn)行適配無疑帶來了更好的性能和用戶體驗(yàn);另外,相對(duì)于一些所謂的「云適配」方案帶來的轉(zhuǎn)換質(zhì)量問題,在基于前后端分離的「定制式」方案中也不會(huì)存在。
    2014-09-09
  • Node.js操作系統(tǒng)OS模塊用法分析

    Node.js操作系統(tǒng)OS模塊用法分析

    這篇文章主要介紹了Node.js操作系統(tǒng)OS模塊用法,結(jié)合實(shí)例形式分析了nodejs OS模塊常見函數(shù)功能及簡單使用技巧,需要的朋友可以參考下
    2019-01-01

最新評(píng)論