Hapi 静态内容

在构建任意一个 web 应用时,不可避免的需要从磁盘提供一些静态文件。有一个名为 inert 的 hapi 插件可以完成这个操作。

首先你需要安装它,并且将 inert 作为依赖添加到你的项目中:

$ npm install --save @hapi/inert

hapi 安装 inert

h.file(path, [options])

首先我们看如何使用 h.file() 方法:

const start = async () => {

    await server.register(require('@hapi/inert'));

    server.route({
        method: 'GET',
        path: '/picture.jpg',
        handler: function (request, h) {

            return h.file('/path/to/picture.jpg');
        }
    });

    await server.start();

    console.log('Server running at:', server.info.uri);
};

start();

如上所示,这就是你返回 h.file(path) 的基本方式。

相对路径

为了简化操作,特别是如果有多个需要返回文件的路由,你可以在服务器中配置基本路径,之后只将相对路径传递给 h.file():

'use strict';

const Hapi = require('@hapi/hapi');
const Path = require('path');

const server = Hapi.server({
    routes: {
        files: {
            relativeTo: Path.join(__dirname, 'public')
        }
    }
});

const start = async () => {

    await server.register(require('@hapi/inert'));

    server.route({
        method: 'GET',
        path: '/picture.jpg',
        handler: function (request, h) {

            return h.file('picture.jpg');
        }
    });

    await server.start();

    console.log('Server running at:', server.info.uri);
};

start();

当在 server.options.routes 中设置一个选项时,如上所述,它将应用于 所有的 路由。你还可以修改这些选项,包括每个路由级别的 relativeTo 选项。


文件 handler

上述路由的替代方法是使用 file handler:

server.route({
    method: 'GET',
    path: '/picture.jpg',
    handler: {
        file: 'picture.jpg'
    }
});

文件 handler 选项

我们还可以将参数指定为接受 request 对象,并返回表示文件路径字符串的函数 (绝对路径或者相对路径):

server.route({
    method: 'GET',
    path: '/{filename}',
    handler: {
        file: function (request) {
            return request.params.filename;
        }
    }
});

它也可以是具有 path 属性的对象。当在 handler 中使用对象时,我们可以附加一些别的东西,如设 Content-Disposition 头并允许压缩文件。如下:

server.route({
    method: 'GET',
    path: '/script.js',
    handler: {
        file: {
            path: 'script.js',
            filename: 'client.js', // 修改 Content-Disposition 头中的文件名
            mode: 'attachment', // 指定 Content-Disposition 是一个附件
            lookupCompressed: true // 如果请求允许,将允许查找 script.js.gz
        }
    }
});

目录 handler

除 file handler 之外,inert 也有一个额外的 directory handler 允许一个路由提供多份文件。要使用它,必须使用参数指定路径。 参数的名称无关紧要,你也可以在参数上使用星号扩展名来限制文件的深度。目录 handler 的基本用法如下:

server.route({
    method: 'GET',
    path: '/{param*}',
    handler: {
        directory: {
            path: 'public'
        }
    }
});

目录 handler 选项

上述路由将通过在 public 目录中查找匹配的文件名来响应任何请求。这里需要注意的是,在此配置中对 / 的请求将会使用 HTTP 403 响应进行回复。我们可以通过添加索引文件的方式来解决这个问题。默认情况下,hapi 会在目录中搜索名为 index.html 的文件。我们可以通过将 index 选项设置为 false 来禁用提供索引文件,或者我们可以指定 inert 可以查找的索引文件数组:

server.route({
    method: 'GET',
    path: '/{param*}',
    handler: {
        directory: {
            path: 'public',
            index: ['index.html', 'default.html']
        }
    }
});

一个发往 / 的请求首先尝试去加载 /index.html, 之后再加载 /default.html。当没有可用的索引文件时, inert 可以以列表的形式显示这个目录下的内容。你可以通过设置 listing 属性为 true 来开启这个选项,如:

server.route({
    method: 'GET',
    path: '/{param*}',
    handler: {
        directory: {
            path: 'public',
            listing: true
        }
    }
});

现在,对 / 的请求将会回复一个显示目录内容的 HTML。使用启用了列表的目录 handler 时,默认情况下隐藏文件不会显示在列表中,可以通过将 showHidden 选项设置为 true 来显示。与文件 handler 一样,目录 handler 也有一个 lookupCompressed 的选项用于提供预压缩文件。你还可以设置一个 defaultExtension,如果找不到原始路径,它将附加到请求中。这意味着对 /bacon 的请求也会尝试文件 /bacon.html

查看笔记

扫码一下
查看教程更方便