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

目录
  • 正文
    • 静态资源服务器
    • 模块化
  • 最后

正文

在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静态资源服务器的资料请关注我们其它相关文章!

(0)

相关推荐

  • Node.js静态服务器的实现方法

    当你输入一个url时,这个url可能对应服务器上的一个资源(文件)也可能对应一个目录. So服务器会对这个url进行分析,针对不同的情况做不同的事. 如果这个url对应的是一个文件,那么服务器就会返回这个文件. 如果这个url对应的是一个文件夹,那么服务器会返回这个文件夹下包含的所有子文件/子文件夹的列表. 以上,就是一个静态服务器所主要干的事. 但真实的情况不会像这么简单, 我们所拿到的url可能是错误的,它所对应的文件或则文件夹或许根本不存在, 又或则有些文件和文件夹是被系统保护起来的是隐藏

  • Node.js一行代码实现静态文件服务器的方法步骤

    静态文件服务器实现 nodejs不仅仅可以用来写服务端接口,用来做静态文件服务器替代nginx的功能, 也是分分钟可以搞定的. 话不多说,先上代码: var server=http.createServer(function (req,res){ fs.createReadStream(Path.resolve(__dirname,"."+req.url)).pipe(res); }) 在项目根目录建一个hello.html文件测试一下 hello.html内容如下: <h1&g

  • 使用Node.js搭建静态资源服务详细教程

    对于Node.js新手,搭建一个静态资源服务器是个不错的锻炼,从最简单的返回文件或错误开始,渐进增强,还可以逐步加深对http的理解.那就开始吧,让我们的双手沾满网络请求! Note: 当然在项目中如果有使用express框架,用express.static一行代码就可以达到目的了: app.use(express.static('public')) 这里我们要实现的正是express.static背后所做工作的一部分,建议同步阅读该模块源码. 基本功能 不急着写下第一行代码,而是先梳理一下就基

  • Node.js动手撸一个静态资源服务器的方法

    简介 本文介绍了一个简单的静态资源服务器的实例项目,希望能给Node.js初学者带来帮助.项目涉及到http.fs.url.path.zlib.process.child_process等模块,涵盖大量常用api:还包括了基于http协议的缓存策略选取.gzip压缩优化等:最终我们会发布到npm上,做成一个可以全局安装.使用的小工具.麻雀虽小,五脏俱全,一想是不是还有点小激动?话不多说,放码过来. 文中源码地址在最后附录中. 可先行体验项目效果: 安装:npm i -g here11 任意文件夹

  • Node.js+jade抓取博客所有文章生成静态html文件的实例

    这篇文章,我们就把上文中采集到的所有文章列表的信息整理一下,开始采集文章并且生成静态html文件了.先看下我的采集效果,我的博客目前77篇文章,1分钟不到就全部采集生成完毕了,这里我截了部分的图片,文件名用文章的id生成的,生成的文章,我写了一个简单的静态模板,所有的文章都是根据这个模板生成的. 项目结构: 好了,接下来,我们就来讲解下,这篇文章主要实现的功能: 1,抓取文章,主要抓取文章的标题,内容,超链接,文章id(用于生成静态html文件) 2,根据jade模板生成html文件 一.抓取文

  • Node.js+jade+mongodb+mongoose实现爬虫分离入库与生成静态文件的方法

    接着这篇文章Node.js+jade抓取博客所有文章生成静态html文件的实例继续,在这篇文章中实现了采集与静态文件的生成,在实际的采集项目中, 应该是先入库再选择性的生成静态文件. 那么我选择的数据库是mongodb,为什么用这个数据库,因为这个数据库是基于集合,数据的操作基本是json,与dom模块cheerio具有非常大的亲和力,cheerio处理过滤出来的数据,可以直接插入mongodb,不需要经过任何的处理,非常的便捷,当然跟node.js的亲和力那就不用说了,更重要的是,性能很棒.这

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

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

  • Node 搭建一个静态资源服务器的实现

    使用 Node 的内置模块,创建一个可以访问目录的静态资源服务器,支持fs文件读取,资源压缩与缓存等. 一.创建 HTTP Server 服务器 Node 的 http 模块提供 HTTP 服务器和客户端接口,通过 require('http') 使用. 先创建一个简单的 http server.配置参数如下: // server/config.js module.exports = { root: process.cwd(), host: '127.0.0.1', port: '8877' }

  • 手写Node静态资源服务器的实现方法

    想写静态资源服务器,首先我们需要知道如何创建一个http服务器,它的原理是什么 http服务器是继承自tcp服务器 http协议是应用层协议,是基于TCP的 http的原理是对请求和响应进行了包装,当客户端连接上来之后先触发connection事件,然后可以多次发送请求,每次请求都会触发request事件 let server = http.createServer(); let url = require('url'); server.on('connection', function (so

  • 基于 Node 实现简易 serve静态资源服务器的示例详解

    目录 前言 基础示例 简易 serve 实现 arg - 命令行参数读取 chalk - 控制台信息输出 源码 扩展 rewrite 和 redirect 的区别? 前言 静态资源服务器(HTTP 服务器)可以将静态文件(如 js.css.图片)等通过 HTTP 协议展现给客户端.本文介绍如何基于 Node 实现一个简易的静态资源服务器(类似于 serve). 基础示例 const fs = require("node:fs"); const fsp = require("n

  • Node.js开发教程之基于OnceIO框架实现文件上传和验证功能

    OnceIO 是 OnceDoc 企业内容(网盘)的底层Web框架,它可以实现模板文件.静态文件的全缓存,运行起来完全不需要I/O操作,并且支持客户端缓存优化,GZIP压缩等(只在第一次压缩),拥有非常好的性能,为您节约服务器成本.它的模块化功能,可以让你的Web进行分布式存储,即一个扩展包里即包含前端.后端和数据库定义,只需通过添加/删除目录的方式就可实现功能删减,实现真正的模块化扩展.这里是介绍如何使用OnceIO的一系列文章. 在这一章节中,我们将为大家演示如何使用 OnceIO 实现文件

  • node.js 开发指南 – Node.js 连接 MySQL 并进行数据库操作

    Node.js是一套用来编写高性能网络服务器的JavaScript工具包   通常在NodeJS开发中我们经常涉及到操作数据库,尤其是 MySQL ,作为应用最为广泛的开源数据库则成为我们的首选,本篇就来介绍下如何通过NodeJS来操作 MySQL 数据库. 安装MySQL模块到NodeJS中 我们需要让NodeJS支持MySQL,则需要将MySQL模块添加到系统支持库   想要快速了解Node.js ,赞生推荐亲看看 node.js_guide.pdf  - node.js 开发指南 :想要电

  • Node.js开发第三方微信公众平台

    一.写在前面的话   Node.js是一个开放源代码.跨平台的JavaScript语言运行环境,采用Google开发的V8运行代码,使用事件驱动.非阻塞和异步输入输出模型等技术来提高性能,可优化应用程序的传输量和规模.这些技术通常用于数据密集的事实应用程序.--来自维基百科   最近花了差不多近一个月的时间去学习Node.js,由于它的代码语言是 Javascript ,因此对于语法上就没有过多的去研究,毕竟做过Web开发的程序员,很少有不会Javascript的.而写这篇文章,也只是为了 如有

  • linux环境安装node.js开发环境搭建图文教程

    Node.js现在有多火,有多重要,就不多说了,这里介绍一下他的开发环境安装,通常情况下,我们都是在window环境进行开发,或者是在mac环境下进行开发,但是我们的项目实际运行的环境一般都是在linux上的,所以我们让我们的开发环境和生产环境能够尽量统一,且能够方便我们开发,一般我们将必要环境安装在服务器上,然后在window上通过xshell,SecureCRTPortable等一些工具连接上去,在window上使用方便IDE软件开发,然后通过ftp将文件同步上去,所以这里就讲一些如何在服务

随机推荐