UNPKG

@fastify/static

Version:

Plugin for serving static files as fast as possible.

229 lines (191 loc) 6.51 kB
import fastify, { type FastifyInstance, type FastifyPluginAsync, type FastifyReply, type FastifyRequest } from 'fastify' import { type Stats } from 'node:fs' import { type Server } from 'node:http' import { expect } from 'tstyche' import * as fastifyStaticStar from '..' import fastifyStatic, { type FastifyStaticOptions, fastifyStatic as fastifyStaticNamed } from '..' const fastifyStaticCjsImport = fastifyStaticStar const fastifyStaticCjs = require('..') const app: FastifyInstance = fastify() app.register(fastifyStatic, { root: __dirname }) app.register(fastifyStaticNamed, { root: __dirname }) app.register(fastifyStaticCjs, { root: __dirname }) app.register(fastifyStaticCjsImport.default, { root: __dirname }) app.register(fastifyStaticCjsImport.fastifyStatic, { root: __dirname }) app.register(fastifyStaticStar.default, { root: __dirname }) app.register(fastifyStaticStar.fastifyStatic, { root: __dirname }) expect(fastifyStatic).type.toBe<FastifyPluginAsync<FastifyStaticOptions, Server>>() expect(fastifyStaticNamed).type.toBe<FastifyPluginAsync<FastifyStaticOptions, Server>>() expect(fastifyStaticCjsImport.default).type.toBe<FastifyPluginAsync<FastifyStaticOptions, Server>>() expect(fastifyStaticCjsImport.fastifyStatic).type.toBe<FastifyPluginAsync<FastifyStaticOptions, Server>>() expect(fastifyStaticStar.default).type.toBe<FastifyPluginAsync<FastifyStaticOptions, Server>>() expect(fastifyStaticStar.fastifyStatic).type.toBe<FastifyPluginAsync<FastifyStaticOptions, Server>>() expect(fastifyStaticCjs).type.toBe<any>() const appWithImplicitHttp = fastify() const options: FastifyStaticOptions = { acceptRanges: true, contentType: true, cacheControl: true, decorateReply: true, dotfiles: 'allow', etag: true, extensions: ['.js'], immutable: true, index: ['1'], lastModified: true, maxAge: '', prefix: '', prefixAvoidTrailingSlash: false, root: '', schemaHide: true, serve: true, wildcard: true, globIgnore: ['**/*.private'], list: false, setHeaders: (reply, path, stat) => { expect(reply).type.toBe<FastifyReply>() expect(reply.statusCode).type.toBe<number>() expect(reply.getHeader('X-Test')).type.toBe<ReturnType<FastifyReply['getHeader']>>() reply.header('X-Test', 'string') expect(path).type.toBe<string>() expect(stat).type.toBe<Stats>() }, preCompressed: false, allowedPath: (_pathName: string, _root: string, _request: FastifyRequest) => { return true }, constraints: { host: /^.*\.example\.com$/, version: '1.0.2' }, logLevel: 'warn', suppressWarning: true } expect<FastifyStaticOptions>() .type.toBeAssignableFrom({ root: '', list: { format: 'json' as const } }) expect<FastifyStaticOptions>() .type.toBeAssignableFrom({ root: '', list: { format: 'json' as const, render: () => '' } }) expect<FastifyStaticOptions>() .type.toBeAssignableFrom({ root: '', list: { format: 'html' as const, render: () => '' } }) expect<FastifyStaticOptions>() .type.toBeAssignableFrom({ root: [''] }) expect<FastifyStaticOptions>() .type.toBeAssignableFrom({ root: new URL('file://') }) expect<FastifyStaticOptions>() .type.toBeAssignableFrom({ root: [new URL('file://')] }) expect<FastifyStaticOptions>() .type.toBeAssignableFrom({ serve: true as const, root: '' }) expect<FastifyStaticOptions>().type.not.toBeAssignableFrom({ serve: true as const, }) appWithImplicitHttp .register(fastifyStatic, options) .after(() => { appWithImplicitHttp.get('/', (_request, reply) => { reply.sendFile('some-file-name') }) }) const appWithHttp2 = fastify({ http2: true }) appWithHttp2 .register(fastifyStatic, options) .after(() => { appWithHttp2.get('/', (_request, reply) => { reply.sendFile('some-file-name') }) appWithHttp2.get('/download', (_request, reply) => { reply.download('some-file-name') }) appWithHttp2.get('/download/1', (_request, reply) => { reply.download('some-file-name', { maxAge: '2 days' }) }) appWithHttp2.get('/download/2', (_request, reply) => { reply.download('some-file-name', 'some-filename', { cacheControl: false, acceptRanges: true }) }) appWithHttp2.get('/download/3', (_request, reply) => { reply.download('some-file-name', 'some-filename', { contentType: false }) }) }) const multiRootAppWithImplicitHttp = fastify() options.root = [''] multiRootAppWithImplicitHttp .register(fastifyStatic, options) .after(() => { multiRootAppWithImplicitHttp.get('/', (_request, reply) => { reply.sendFile('some-file-name') }) multiRootAppWithImplicitHttp.get('/', (_request, reply) => { reply.sendFile('some-file-name', { cacheControl: false, acceptRanges: true }) }) multiRootAppWithImplicitHttp.get('/', (_request, reply) => { reply.sendFile('some-file-name', 'some-root-name', { cacheControl: false, acceptRanges: true }) }) multiRootAppWithImplicitHttp.get('/', (_request, reply) => { reply.sendFile('some-file-name', 'some-root-name-2', { contentType: false }) }) multiRootAppWithImplicitHttp.get('/download', (_request, reply) => { reply.download('some-file-name') }) multiRootAppWithImplicitHttp.get('/download/1', (_request, reply) => { reply.download('some-file-name', { maxAge: '2 days' }) }) multiRootAppWithImplicitHttp.get('/download/2', (_request, reply) => { reply.download('some-file-name', 'some-filename', { cacheControl: false, acceptRanges: true }) }) multiRootAppWithImplicitHttp.get('/download/3', (_request, reply) => { reply.download('some-file-name', 'some-filename', { contentType: false }) }) }) const noIndexApp = fastify() options.root = '' options.index = false noIndexApp .register(fastifyStatic, options) .after(() => { noIndexApp.get('/', (_request, reply) => { reply.send('<h1>fastify-static</h1>') }) }) options.root = new URL('file://') const URLRootApp = fastify() URLRootApp.register(fastifyStatic, options) .after(() => { URLRootApp.get('/', (_request, reply) => { reply.send('<h1>fastify-static</h1>') }) }) const defaultIndexApp = fastify() options.index = 'index.html' as const defaultIndexApp .register(fastifyStatic, options) .after(() => { defaultIndexApp.get('/', (_request, reply) => { reply.send('<h1>fastify-static</h1>') }) })