Node.js开发静态资源服务器

 更新时间:2022年8月8日 22:11  点击:1024 作者:爱吃鱼的桶哥Z

正文

在09年Node.js出来后,让前端开发人员的开发路线变的不再那么单调,经过这么多年的发展,我们的开发基本已经离不开Node.js,不管是用作于工具类的开发,还是做完服务端的中间层,Node.js都占据了非常重要的地位,今天我们就一起通过原生的js+Node来实现一个简单的静态资源服务,如果你还不了解这方面的知识,那就跟我一起来学习吧!

静态资源服务器

Node.js经过这么多年的发展,已经有了很多很优秀的基础框架或类库,像express.jsKoa.jsegg.js等,它们都是基于原生的Node.js来实现的,而我们之所以不选择用这些框架,其实就是希望大家能够了解前面这几种框架是如何实现一个基础的静态资源服务的,只有当我们了解了这其中的知识点,再使用这些框架时才会更加得心应手,下面我们一起看一下这个基础的静态资源服务该如何开发吧!

首先,我们要了解的是,既然是要开发静态资源服务,那么什么是静态资源服务呢?简单来说就是可以静态访问的一个资源服务器,而这些静态资源包括但不限于类似htmlcssjs以及一些图片资源,音视频等等。我们能通过网络直接访问这些内容,就是因为它们通过静态资源服务器将这些内容挂载在网上。

我们首先要做的就是创建一个服务,在Node中我们通过http模块来创建一个服务,httpNode中的一个基础的API,相关的内容可以查阅官方文档,然后我们需要读取本地的资源,那么就需要用到另外一个模块fsfs模块能够操作本地的资源文件,具体的内容也可以通过官网的文档进行查看,下面我们一起来看一下相关的代码,代码如下:

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中一些简单的API就开发了一个基础的静态资源服务器,也让大家了解了一些Node.js相关的基础操作,了解这些基础的操作不仅有利于提高我们自身的知识储备,也更有利于我们在实际开发中少踩一些坑。

以上就是Node.js开发静态资源服务器的详细内容,更多关于Node.js静态资源服务器的资料请关注猪先飞其它相关文章!

原文出处:https://juejin.cn/post/7129118723897720840

[!--infotagslink--]

相关文章

  • 分享一段php获取linux服务器状态的代码

    简单的php获取linux服务器状态的代码,不多说-直接上函数:复制代码 代码如下:function get_used_status(){ $fp = popen('top -b -n 2 | grep -E "^(Cpu|Mem|Tasks)"',"r");//获取某一时刻系统cpu和内存使用情况 $rs =...2014-05-31
  • Springboot+TCP监听服务器搭建过程图解

    这篇文章主要介绍了Springboot+TCP监听服务器搭建过程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-10-28
  • node.JS md5加密中文与php结果不一致怎么办

    这次文章要给大家介绍的是node.JS md5加密中文与php结果不一致怎么办,不知道具体解决办法的下面跟小编一起来看看。 因项目需要,需要Node.js与PHP做接口调用,发现nod...2017-07-06
  • NODE.JS加密模块CRYPTO常用方法介绍

    使用require('crypto')调用加密模块。加密模块需要底层系统提供OpenSSL的支持。它提供了一种安全凭证的封装方式,可以用于HTTPS安全网络以及普通HTTP连接。该模块还提供了一套针对OpenSSL的hash(哈希),hmac(密钥哈希),cipher...2014-06-07
  • 服务器 UDP端口占用几千个的解决办法

    前一段时间使用NetStat命令查看服务器端口时,发现服务器udp端口开放了好多,最少在1000个以上,当时事情比较多,没有管它,今天终于有点时间,仔细检查了一下,排除了这个问题. ...2016-01-27
  • 浅谈node.js中async异步编程

    1.什么是异步编程? 异步编程是指由于异步I/O等因素,无法同步获得执行结果时, 在回调函数中进行下一步操作的代码编写风格,常见的如setTimeout函数、ajax请求等等。示例: for (var i = 1; i <= 3; i++) {setTimeout(functi...2015-10-23
  • node.js+express留言板功能实现示例

    本文介绍基于nodejs+express+art-template的留言板功能。包含列表界面、添加界面和发送留言功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-21
  • PHP连接公司内部服务器的MYSQL数据库的简单实例

    “主机,用户名,密码”得到连接、“数据库,sql,连接”得到结果,最后是结果的处理显示。当然,数据库连接是扩展库为我们完成的,我们能做的仅仅是处理结果而已。...2013-09-29
  • 安装使用Mongoose配合Node.js操作MongoDB的基础教程

    这篇文章主要介绍了安装使用Mongoose来让Node.js操作MongoDB的基础教程,前端js+后端node+js操作MongoDB正是所谓最流行的一种JavaScript全栈开发方案,需要的朋友可以参考下...2016-03-03
  • 解决HttpPost+json请求---服务器中文乱码及其他问题

    这篇文章主要介绍了解决HttpPost+json请求---服务器中文乱码及其他问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-22
  • 详解SpringBoot之访问静态资源(webapp...)

    这篇文章主要介绍了详解SpringBoot之访问静态资源(webapp...),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-09-14
  • node.js从数据库获取数据

    这篇文章主要为大家详细介绍了node.js从数据库获取数据的具体代码,nodejs可以获取具体某张数据表信息,感兴趣的朋友可以参考一下...2016-05-09
  • 利用Node.js获取项目根目录的小技巧

    这篇文章介绍的是一个小技巧来获取node.js项目根目录,这个技巧非常实用。有需要的朋友们可以参考借鉴,下面来一起看看吧。...2016-10-02
  • 比较node.js和Deno

    这篇文章主要介绍了node.js和Deno的区别,对deno感兴趣的同学,可以参考下...2021-04-27
  • Node.js之http模块的用法

    这篇文章主要介绍了Node.js之http模块的用法,对Node.js感兴趣的同学,可以参考下...2021-04-25
  • Hyper-V尝试连接到服务器出错无效类的解决方法

    这篇文章主要介绍了Hyper-V尝试连接到服务器出错无效类的解决方法,需要的朋友可以参考下...2016-09-28
  • 三种Node.js写文件的方式

    这篇文章主要为大家详细介绍了三种Node.js写文件的方式,感兴趣的小伙伴们可以参考一下...2016-03-10
  • mac使用Shell(终端)SSH连接远程服务器的方法

    这篇文章主要介绍了mac使用Shell(终端)SSH连接远程服务器的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-07-11
  • js实现上传图片到服务器

    这篇文章主要为大家详细介绍了js实现上传图片到服务器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-04-11
  • node.js [superAgent] 请求使用示例

    post请求:复制代码 代码如下: request.post('/api/pet') .end(function(resp,err){ if (resp.body.status===200) { alert('yay got ' + JSON.stringify(res.body)); } else { return nex...2015-03-15