You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					3483 lines
				
				95 KiB
			
		
		
			
		
	
	
					3483 lines
				
				95 KiB
			| 
											3 years ago
										 | 'use strict' | ||
|  | 
 | ||
|  | /* eslint node/no-deprecated-api: "off" */ | ||
|  | 
 | ||
|  | const path = require('path') | ||
|  | const fs = require('fs') | ||
|  | const url = require('url') | ||
|  | const http = require('http') | ||
|  | const t = require('tap') | ||
|  | const simple = require('simple-get') | ||
|  | const Fastify = require('fastify') | ||
|  | const { kErrorHandler } = require('fastify/lib/symbols') | ||
|  | const compress = require('fastify-compress') | ||
|  | const concat = require('concat-stream') | ||
|  | const pino = require('pino') | ||
|  | const proxyquire = require('proxyquire') | ||
|  | 
 | ||
|  | const fastifyStatic = require('../') | ||
|  | 
 | ||
|  | const indexContent = fs | ||
|  |   .readFileSync('./test/static/index.html') | ||
|  |   .toString('utf8') | ||
|  | const index2Content = fs | ||
|  |   .readFileSync('./test/static2/index.html') | ||
|  |   .toString('utf8') | ||
|  | const foobarContent = fs | ||
|  |   .readFileSync('./test/static/foobar.html') | ||
|  |   .toString('utf8') | ||
|  | const deepContent = fs | ||
|  |   .readFileSync('./test/static/deep/path/for/test/purpose/foo.html') | ||
|  |   .toString('utf8') | ||
|  | const innerIndex = fs | ||
|  |   .readFileSync('./test/static/deep/path/for/test/index.html') | ||
|  |   .toString('utf8') | ||
|  | const allThreeBr = fs.readFileSync( | ||
|  |   './test/static-pre-compressed/all-three.html.br' | ||
|  | ) | ||
|  | const allThreeGzip = fs.readFileSync( | ||
|  |   './test/static-pre-compressed/all-three.html.gz' | ||
|  | ) | ||
|  | const gzipOnly = fs.readFileSync( | ||
|  |   './test/static-pre-compressed/gzip-only.html.gz' | ||
|  | ) | ||
|  | const indexBr = fs.readFileSync( | ||
|  |   './test/static-pre-compressed/index.html.br' | ||
|  | ) | ||
|  | const dirIndexBr = fs.readFileSync( | ||
|  |   './test/static-pre-compressed/dir/index.html.br' | ||
|  | ) | ||
|  | const uncompressedStatic = fs | ||
|  |   .readFileSync('./test/static-pre-compressed/uncompressed.html') | ||
|  |   .toString('utf8') | ||
|  | const fooContent = fs.readFileSync('./test/static/foo.html').toString('utf8') | ||
|  | const barContent = fs.readFileSync('./test/static2/bar.html').toString('utf8') | ||
|  | 
 | ||
|  | const GENERIC_RESPONSE_CHECK_COUNT = 5 | ||
|  | function genericResponseChecks (t, response) { | ||
|  |   t.ok(/text\/(html|css)/.test(response.headers['content-type'])) | ||
|  |   t.ok(response.headers.etag) | ||
|  |   t.ok(response.headers['last-modified']) | ||
|  |   t.ok(response.headers.date) | ||
|  |   t.ok(response.headers['cache-control']) | ||
|  | } | ||
|  | 
 | ||
|  | const GENERIC_ERROR_RESPONSE_CHECK_COUNT = 2 | ||
|  | function genericErrorResponseChecks (t, response) { | ||
|  |   t.equal(response.headers['content-type'], 'application/json; charset=utf-8') | ||
|  |   t.ok(response.headers.date) | ||
|  | } | ||
|  | 
 | ||
|  | t.test('register /static prefixAvoidTrailingSlash', t => { | ||
|  |   t.plan(12) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static', | ||
|  |     prefixAvoidTrailingSlash: true | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/static/index.html', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/index.css', (t) => { | ||
|  |       t.plan(2 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/index.css' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/deep/path/for/test/purpose/foo.html', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/deep/path/for/test/purpose/foo.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), deepContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/deep/path/for/test/', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/deep/path/for/test/' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), innerIndex) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/this/path/for/test', (t) => { | ||
|  |       t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/this/path/for/test', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |         genericErrorResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/this/path/doesnt/exist.html', (t) => { | ||
|  |       t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/this/path/doesnt/exist.html', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |         genericErrorResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/../index.js', (t) => { | ||
|  |       t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/../index.js', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 403) | ||
|  |         genericErrorResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('file not exposed outside of the plugin', (t) => { | ||
|  |       t.plan(2) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         // foobar is in static
 | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/foobar.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('file not exposed outside of the plugin', t => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'HEAD', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), '') | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('register /static', (t) => { | ||
|  |   t.plan(11) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static' | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/static/index.html', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/index.css', (t) => { | ||
|  |       t.plan(2 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/index.css' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static', (t) => { | ||
|  |       t.plan(2) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/deep/path/for/test/purpose/foo.html', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/deep/path/for/test/purpose/foo.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), deepContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/deep/path/for/test/', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/deep/path/for/test/' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), innerIndex) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/this/path/for/test', (t) => { | ||
|  |       t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/this/path/for/test', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |         genericErrorResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/this/path/doesnt/exist.html', (t) => { | ||
|  |       t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/this/path/doesnt/exist.html', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |         genericErrorResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/../index.js', (t) => { | ||
|  |       t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/../index.js', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 403) | ||
|  |         genericErrorResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('file not exposed outside of the plugin', (t) => { | ||
|  |       t.plan(2) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         // foobar is in static
 | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/foobar.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('register /static/', t => { | ||
|  |   t.plan(12) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static/' | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/static/index.html', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/index.html', t => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'HEAD', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), '') | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/index.css', (t) => { | ||
|  |       t.plan(2 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/index.css' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static', (t) => { | ||
|  |       t.plan(2) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/deep/path/for/test/purpose/foo.html', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/deep/path/for/test/purpose/foo.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), deepContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/deep/path/for/test/', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/deep/path/for/test/' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), innerIndex) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/this/path/for/test', (t) => { | ||
|  |       t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/this/path/for/test', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |         genericErrorResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/this/path/doesnt/exist.html', (t) => { | ||
|  |       t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/this/path/doesnt/exist.html', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |         genericErrorResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/../index.js', (t) => { | ||
|  |       t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/../index.js', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 403) | ||
|  |         genericErrorResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('304', t => { | ||
|  |       t.plan(5 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         const etag = response.headers.etag | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  | 
 | ||
|  |         simple.concat({ | ||
|  |           method: 'GET', | ||
|  |           url: 'http://localhost:' + fastify.server.address().port + '/static/index.html', | ||
|  |           headers: { | ||
|  |             'if-none-match': etag | ||
|  |           } | ||
|  |         }, (err, response, body) => { | ||
|  |           t.error(err) | ||
|  |           t.equal(response.statusCode, 304) | ||
|  |         }) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('register /static and /static2', (t) => { | ||
|  |   t.plan(5) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: [path.join(__dirname, '/static'), path.join(__dirname, '/static2')], | ||
|  |     prefix: '/static' | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   fastify.get('/foo', (req, rep) => { | ||
|  |     rep.sendFile('foo.html') | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.get('/bar', (req, rep) => { | ||
|  |     rep.sendFile('bar.html') | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/static/index.html', (t) => { | ||
|  |       t.plan(4 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.not(body.toString(), index2Content) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/bar.html', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/bar.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), barContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('sendFile foo.html', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/foo' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), fooContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('sendFile bar.html', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/bar' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), barContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('payload.filename is set', (t) => { | ||
|  |   t.plan(3) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static/' | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   let gotFilename | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  |   fastify.addHook('onSend', function (req, reply, payload, next) { | ||
|  |     gotFilename = payload.filename | ||
|  |     next() | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/static/index.html', (t) => { | ||
|  |       t.plan(5 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         t.equal(typeof gotFilename, 'string') | ||
|  |         t.equal(gotFilename, path.join(pluginOptions.root, 'index.html')) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/this/path/doesnt/exist.html', (t) => { | ||
|  |       t.plan(3 + GENERIC_ERROR_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/this/path/doesnt/exist.html', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |         t.equal(typeof gotFilename, 'undefined') | ||
|  |         genericErrorResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('error responses can be customized with fastify.setErrorHandler()', t => { | ||
|  |   t.plan(2) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static') | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.setErrorHandler(function errorHandler (err, request, reply) { | ||
|  |     reply.type('text/plain').send(err.status + ' Custom error message') | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/../index.js', t => { | ||
|  |       t.plan(4) | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/../index.js', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 403) | ||
|  |         t.equal(response.headers['content-type'], 'text/plain') | ||
|  |         t.equal(body.toString(), '403 Custom error message') | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('not found responses can be customized with fastify.setNotFoundHandler()', t => { | ||
|  |   t.plan(2) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static') | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.setNotFoundHandler(function notFoundHandler (request, reply) { | ||
|  |     reply.code(404).type('text/plain').send(request.raw.url + ' Not Found') | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/path/does/not/exist.html', t => { | ||
|  |       t.plan(4) | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/path/does/not/exist.html', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |         t.equal(response.headers['content-type'], 'text/plain') | ||
|  |         t.equal(body.toString(), '/path/does/not/exist.html Not Found') | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('fastify.setNotFoundHandler() is called for dotfiles when when send is configured to ignore dotfiles', t => { | ||
|  |   t.plan(2) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     send: { | ||
|  |       dotfiles: 'ignore' | ||
|  |     } | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.setNotFoundHandler(function notFoundHandler (request, reply) { | ||
|  |     reply.code(404).type('text/plain').send(request.raw.url + ' Not Found') | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     // Requesting files with a leading dot doesn't follow the same code path as
 | ||
|  |     // other 404 errors
 | ||
|  |     t.test('/path/does/not/.exist.html', t => { | ||
|  |       t.plan(4) | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/path/does/not/.exist.html', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |         t.equal(response.headers['content-type'], 'text/plain') | ||
|  |         t.equal(body.toString(), '/path/does/not/.exist.html Not Found') | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('serving disabled', (t) => { | ||
|  |   t.plan(3) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static/', | ||
|  |     serve: false | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   fastify.get('/foo/bar', (request, reply) => { | ||
|  |     return reply.sendFile('index.html') | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/static/index.html not found', (t) => { | ||
|  |       t.plan(2) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/index.html via sendFile found', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/foo/bar' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('sendFile', (t) => { | ||
|  |   t.plan(5) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static' | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   const maxAge = Math.round(Math.random() * 10) * 10000 | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   fastify.get('/foo/bar', function (req, reply) { | ||
|  |     return reply.sendFile('/index.html') | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.get('/root/path/override/test', (request, reply) => { | ||
|  |     return reply.sendFile( | ||
|  |       '/foo.html', | ||
|  |       path.join(__dirname, 'static', 'deep', 'path', 'for', 'test', 'purpose') | ||
|  |     ) | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.get('/foo/bar/options/override/test', function (req, reply) { | ||
|  |     return reply.sendFile('/index.html', { maxAge }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('reply.sendFile()', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/foo/bar', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('reply.sendFile() with rootPath', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/root/path/override/test', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), deepContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('reply.sendFile() again without root path', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/foo/bar', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('reply.sendFile() with options', (t) => { | ||
|  |       t.plan(4 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/foo/bar/options/override/test', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(response.headers['cache-control'], `public, max-age=${maxAge / 1000}`) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('sendFile disabled', (t) => { | ||
|  |   t.plan(2) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static', | ||
|  |     decorateReply: false | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   fastify.get('/foo/bar', function (req, reply) { | ||
|  |     if (typeof reply.sendFile === 'undefined') { | ||
|  |       reply.send('pass') | ||
|  |     } else { | ||
|  |       reply.send('fail') | ||
|  |     } | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('reply.sendFile undefined', (t) => { | ||
|  |       t.plan(3) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/foo/bar', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), 'pass') | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('allowedPath option', (t) => { | ||
|  |   t.plan(3) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     allowedPath: (pathName) => pathName !== '/foobar.html' | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/foobar.html not found', (t) => { | ||
|  |       t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/foobar.html', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |         genericErrorResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/index.css found', (t) => { | ||
|  |       t.plan(2) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/index.css', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('download', (t) => { | ||
|  |   t.plan(7) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static' | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   fastify.get('/foo/bar', function (req, reply) { | ||
|  |     return reply.download('/index.html') | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.get('/foo/bar/change', function (req, reply) { | ||
|  |     return reply.download('/index.html', 'hello-world.html') | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.get('/foo/bar/override', function (req, reply) { | ||
|  |     return reply.download('/index.html', 'hello-world.html', { | ||
|  |       maxAge: '2 hours', | ||
|  |       immutable: true | ||
|  |     }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.get('/foo/bar/override/2', function (req, reply) { | ||
|  |     return reply.download('/index.html', { acceptRanges: false }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.get('/root/path/override/test', (request, reply) => { | ||
|  |     return reply.download('/foo.html', { | ||
|  |       root: path.join( | ||
|  |         __dirname, | ||
|  |         'static', | ||
|  |         'deep', | ||
|  |         'path', | ||
|  |         'for', | ||
|  |         'test', | ||
|  |         'purpose' | ||
|  |       ) | ||
|  |     }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.get('/root/path/override/test/change', (request, reply) => { | ||
|  |     return reply.download('/foo.html', 'hello-world.html', { | ||
|  |       root: path.join( | ||
|  |         __dirname, | ||
|  |         'static', | ||
|  |         'deep', | ||
|  |         'path', | ||
|  |         'for', | ||
|  |         'test', | ||
|  |         'purpose' | ||
|  |       ) | ||
|  |     }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('reply.download()', (t) => { | ||
|  |       t.plan(4 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/foo/bar', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(response.headers['content-disposition'], 'attachment; filename="index.html"') | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('reply.download() with fileName', t => { | ||
|  |       t.plan(4 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/foo/bar/change', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(response.headers['content-disposition'], 'attachment; filename="hello-world.html"') | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('reply.download() with fileName', (t) => { | ||
|  |       t.plan(4 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/root/path/override/test', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(response.headers['content-disposition'], 'attachment; filename="foo.html"') | ||
|  |         t.equal(body.toString(), deepContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('reply.download() with custom opts', (t) => { | ||
|  |       t.plan(5 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/foo/bar/override', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(response.headers['content-disposition'], 'attachment; filename="hello-world.html"') | ||
|  |         t.equal(response.headers['cache-control'], 'public, max-age=7200, immutable') | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('reply.download() with custom opts (2)', (t) => { | ||
|  |       t.plan(5 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/foo/bar/override/2', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(response.headers['content-disposition'], 'attachment; filename="index.html"') | ||
|  |         t.equal(response.headers['accept-ranges'], undefined) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('reply.download() with rootPath and fileName', (t) => { | ||
|  |       t.plan(4 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/root/path/override/test/change', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(response.headers['content-disposition'], 'attachment; filename="hello-world.html"') | ||
|  |         t.equal(body.toString(), deepContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('sendFile disabled', (t) => { | ||
|  |   t.plan(2) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static', | ||
|  |     decorateReply: false | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   fastify.get('/foo/bar', function (req, reply) { | ||
|  |     if (typeof reply.sendFile === 'undefined') { | ||
|  |       reply.send('pass') | ||
|  |     } else { | ||
|  |       reply.send('fail') | ||
|  |     } | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('reply.sendFile undefined', (t) => { | ||
|  |       t.plan(3) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/foo/bar', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), 'pass') | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('download disabled', (t) => { | ||
|  |   t.plan(3) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static', | ||
|  |     decorateReply: false | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   fastify.get('/foo/bar', function (req, reply) { | ||
|  |     if (typeof reply.download === 'undefined') { | ||
|  |       t.equal(reply.download, undefined) | ||
|  |       reply.send('pass') | ||
|  |     } else { | ||
|  |       reply.send('fail') | ||
|  |     } | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('reply.sendFile undefined', (t) => { | ||
|  |       t.plan(3) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/foo/bar', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), 'pass') | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('prefix default', (t) => { | ||
|  |   t.plan(1) | ||
|  |   const pluginOptions = { root: path.join(__dirname, 'static') } | ||
|  |   const fastify = Fastify({ logger: false }) | ||
|  |   t.doesNotThrow(() => fastify.register(fastifyStatic, pluginOptions)) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('root not found warning', (t) => { | ||
|  |   t.plan(2) | ||
|  |   const rootPath = path.join(__dirname, 'does-not-exist') | ||
|  |   const pluginOptions = { root: rootPath } | ||
|  |   const destination = concat((data) => { | ||
|  |     t.equal(JSON.parse(data).msg, `"root" path "${rootPath}" must exist`) | ||
|  |   }) | ||
|  |   const logger = pino( | ||
|  |     { | ||
|  |       level: 'warn' | ||
|  |     }, | ||
|  |     destination | ||
|  |   ) | ||
|  |   const fastify = Fastify({ logger: logger }) | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  |     fastify.server.unref() | ||
|  |     destination.end() | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('send options', (t) => { | ||
|  |   t.plan(11) | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     acceptRanges: 'acceptRanges', | ||
|  |     cacheControl: 'cacheControl', | ||
|  |     dotfiles: 'dotfiles', | ||
|  |     etag: 'etag', | ||
|  |     extensions: 'extensions', | ||
|  |     immutable: 'immutable', | ||
|  |     index: 'index', | ||
|  |     lastModified: 'lastModified', | ||
|  |     maxAge: 'maxAge' | ||
|  |   } | ||
|  |   const fastify = Fastify({ logger: false }) | ||
|  |   const fastifyStatic = require('proxyquire')('../', { | ||
|  |     send: function sendStub (req, pathName, options) { | ||
|  |       t.equal(pathName, '/index.html') | ||
|  |       t.equal(options.root, path.join(__dirname, '/static')) | ||
|  |       t.equal(options.acceptRanges, 'acceptRanges') | ||
|  |       t.equal(options.cacheControl, 'cacheControl') | ||
|  |       t.equal(options.dotfiles, 'dotfiles') | ||
|  |       t.equal(options.etag, 'etag') | ||
|  |       t.equal(options.extensions, 'extensions') | ||
|  |       t.equal(options.immutable, 'immutable') | ||
|  |       t.equal(options.index, 'index') | ||
|  |       t.equal(options.lastModified, 'lastModified') | ||
|  |       t.equal(options.maxAge, 'maxAge') | ||
|  |       return { on: () => { }, pipe: () => { } } | ||
|  |     } | ||
|  |   }) | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  |   fastify.inject({ url: '/index.html' }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('setHeaders option', (t) => { | ||
|  |   t.plan(6 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, 'static'), | ||
|  |     setHeaders: function (res, pathName) { | ||
|  |       t.equal(pathName, path.join(__dirname, 'static/index.html')) | ||
|  |       res.setHeader('X-Test-Header', 'test') | ||
|  |     } | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     simple.concat({ | ||
|  |       method: 'GET', | ||
|  |       url: 'http://localhost:' + fastify.server.address().port + '/index.html', | ||
|  |       followRedirect: false | ||
|  |     }, (err, response, body) => { | ||
|  |       t.error(err) | ||
|  |       t.equal(response.statusCode, 200) | ||
|  |       t.equal(response.headers['x-test-header'], 'test') | ||
|  |       t.equal(body.toString(), indexContent) | ||
|  |       genericResponseChecks(t, response) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('maxAge option', (t) => { | ||
|  |   t.plan(5 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, 'static'), | ||
|  |     maxAge: 3600000 | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     simple.concat({ | ||
|  |       method: 'GET', | ||
|  |       url: 'http://localhost:' + fastify.server.address().port + '/index.html', | ||
|  |       followRedirect: false | ||
|  |     }, (err, response, body) => { | ||
|  |       t.error(err) | ||
|  |       t.equal(response.statusCode, 200) | ||
|  |       t.equal(response.headers['cache-control'], 'public, max-age=3600') | ||
|  |       t.equal(body.toString(), indexContent) | ||
|  |       genericResponseChecks(t, response) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('errors', (t) => { | ||
|  |   t.plan(11) | ||
|  | 
 | ||
|  |   t.test('no root', (t) => { | ||
|  |     t.plan(1) | ||
|  |     const pluginOptions = {} | ||
|  |     const fastify = Fastify({ logger: false }) | ||
|  |     fastify.register(fastifyStatic, pluginOptions).ready((err) => { | ||
|  |       t.equal(err.constructor, Error) | ||
|  |     }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.test('root is not a string', (t) => { | ||
|  |     t.plan(1) | ||
|  |     const pluginOptions = { root: 42 } | ||
|  |     const fastify = Fastify({ logger: false }) | ||
|  |     fastify.register(fastifyStatic, pluginOptions).ready((err) => { | ||
|  |       t.equal(err.constructor, Error) | ||
|  |     }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.test('root is not an absolute path', (t) => { | ||
|  |     t.plan(1) | ||
|  |     const pluginOptions = { root: './my/path' } | ||
|  |     const fastify = Fastify({ logger: false }) | ||
|  |     fastify.register(fastifyStatic, pluginOptions).ready((err) => { | ||
|  |       t.equal(err.constructor, Error) | ||
|  |     }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.test('root is not a directory', (t) => { | ||
|  |     t.plan(1) | ||
|  |     const pluginOptions = { root: __filename } | ||
|  |     const fastify = Fastify({ logger: false }) | ||
|  |     fastify.register(fastifyStatic, pluginOptions).ready((err) => { | ||
|  |       t.equal(err.constructor, Error) | ||
|  |     }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.test('root is an empty array', (t) => { | ||
|  |     t.plan(1) | ||
|  |     const pluginOptions = { root: [] } | ||
|  |     const fastify = Fastify({ logger: false }) | ||
|  |     fastify.register(fastifyStatic, pluginOptions).ready((err) => { | ||
|  |       t.equal(err.constructor, Error) | ||
|  |     }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.test('root array does not contain strings', (t) => { | ||
|  |     t.plan(1) | ||
|  |     const pluginOptions = { root: [1] } | ||
|  |     const fastify = Fastify({ logger: false }) | ||
|  |     fastify.register(fastifyStatic, pluginOptions).ready((err) => { | ||
|  |       t.equal(err.constructor, Error) | ||
|  |     }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.test('root array does not contain an absolute path', (t) => { | ||
|  |     t.plan(1) | ||
|  |     const pluginOptions = { root: ['./my/path'] } | ||
|  |     const fastify = Fastify({ logger: false }) | ||
|  |     fastify.register(fastifyStatic, pluginOptions).ready((err) => { | ||
|  |       t.equal(err.constructor, Error) | ||
|  |     }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.test('root array path is not a directory', (t) => { | ||
|  |     t.plan(1) | ||
|  |     const pluginOptions = { root: [__filename] } | ||
|  |     const fastify = Fastify({ logger: false }) | ||
|  |     fastify.register(fastifyStatic, pluginOptions).ready((err) => { | ||
|  |       t.equal(err.constructor, Error) | ||
|  |     }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.test('all root array paths must be valid', (t) => { | ||
|  |     t.plan(1) | ||
|  |     const pluginOptions = { root: [path.join(__dirname, '/static'), 1] } | ||
|  |     const fastify = Fastify({ logger: false }) | ||
|  |     fastify.register(fastifyStatic, pluginOptions).ready((err) => { | ||
|  |       t.equal(err.constructor, Error) | ||
|  |     }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.test('duplicate root paths are not allowed', (t) => { | ||
|  |     t.plan(1) | ||
|  |     const pluginOptions = { | ||
|  |       root: [path.join(__dirname, '/static'), path.join(__dirname, '/static')] | ||
|  |     } | ||
|  |     const fastify = Fastify({ logger: false }) | ||
|  |     fastify.register(fastifyStatic, pluginOptions).ready((err) => { | ||
|  |       t.equal(err.constructor, Error) | ||
|  |     }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.test('setHeaders is not a function', (t) => { | ||
|  |     t.plan(1) | ||
|  |     const pluginOptions = { root: __dirname, setHeaders: 'headers' } | ||
|  |     const fastify = Fastify({ logger: false }) | ||
|  |     fastify.register(fastifyStatic, pluginOptions).ready((err) => { | ||
|  |       t.equal(err.constructor, TypeError) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('register no prefix', (t) => { | ||
|  |   t.plan(8) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static') | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   fastify.get('/', (request, reply) => { | ||
|  |     reply.send({ hello: 'world' }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/index.html', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/index.css', (t) => { | ||
|  |       t.plan(2 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/index.css' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/', (t) => { | ||
|  |       t.plan(3) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.same(JSON.parse(body), { hello: 'world' }) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/deep/path/for/test/purpose/foo.html', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/deep/path/for/test/purpose/foo.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), deepContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/deep/path/for/test/', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/deep/path/for/test/' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), innerIndex) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/this/path/doesnt/exist.html', (t) => { | ||
|  |       t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/this/path/doesnt/exist.html', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |         genericErrorResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/../index.js', (t) => { | ||
|  |       t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/../index.js', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 403) | ||
|  |         genericErrorResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('with fastify-compress', t => { | ||
|  |   t.plan(3) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static') | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(compress, { threshold: 0 }) | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     t.test('deflate', function (t) { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/index.html', | ||
|  |         headers: { | ||
|  |           'accept-encoding': ['deflate'] | ||
|  |         } | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(response.headers['content-encoding'], 'deflate') | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('gzip', function (t) { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(response.headers['content-encoding'], 'gzip') | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | t.test('register /static/ with schemaHide true', t => { | ||
|  |   t.plan(4) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static/', | ||
|  |     schemaHide: true | ||
|  |   } | ||
|  | 
 | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.addHook('onRoute', function (routeOptions) { | ||
|  |     t.same(routeOptions.schema, { hide: true }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/static/index.html', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('register /static/ with schemaHide false', t => { | ||
|  |   t.plan(4) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static/', | ||
|  |     schemaHide: false | ||
|  |   } | ||
|  | 
 | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.addHook('onRoute', function (routeOptions) { | ||
|  |     t.same(routeOptions.schema, { hide: false }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/static/index.html', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('register /static/ without schemaHide', t => { | ||
|  |   t.plan(4) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static/' | ||
|  |   } | ||
|  | 
 | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.addHook('onRoute', function (routeOptions) { | ||
|  |     t.same(routeOptions.schema, { hide: true }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/static/index.html', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('fastify with exposeHeadRoutes', t => { | ||
|  |   t.plan(2) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     wildcard: false | ||
|  |   } | ||
|  |   const fastify = Fastify({ exposeHeadRoutes: true }) | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   fastify.get('/*', (request, reply) => { | ||
|  |     reply.send({ hello: 'world' }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/index.html', t => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'HEAD', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), '') | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('register with wildcard false', t => { | ||
|  |   t.plan(9) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     wildcard: false | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   fastify.get('/*', (request, reply) => { | ||
|  |     reply.send({ hello: 'world' }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/index.html', t => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/index.css', (t) => { | ||
|  |       t.plan(2 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/index.css' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/not-defined', (t) => { | ||
|  |       t.plan(3) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/not-defined' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.same(JSON.parse(body), { hello: 'world' }) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/deep/path/for/test/purpose/foo.html', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/deep/path/for/test/purpose/foo.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), deepContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/deep/path/for/test/', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/deep/path/for/test/' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), innerIndex) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/../index.js', (t) => { | ||
|  |       t.plan(3) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/../index.js', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.same(JSON.parse(body), { hello: 'world' }) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/index.css', t => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'HEAD', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/index.css' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), '') | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('register with wildcard string', (t) => { | ||
|  |   t.plan(1) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     wildcard: '**/index.html' | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   fastify.get('/*', (request, reply) => { | ||
|  |     reply.send({ hello: 'world' }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.ready(function (err) { | ||
|  |     t.ok(err) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('register with wildcard string on multiple root paths', (t) => { | ||
|  |   t.plan(1) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: [path.join(__dirname, '/static'), path.join(__dirname, '/static2')], | ||
|  |     wildcard: '**/*.js' | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   fastify.get('/*', (request, reply) => { | ||
|  |     reply.send({ hello: 'world' }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.ok(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('register with wildcard false and alternative index', t => { | ||
|  |   t.plan(11) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     wildcard: false, | ||
|  |     index: ['foobar.html', 'foo.html', 'index.html'] | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   fastify.get('/*', (request, reply) => { | ||
|  |     reply.send({ hello: 'world' }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/index.html', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/index.html', t => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'HEAD', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), '') | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/index.css', (t) => { | ||
|  |       t.plan(2 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/index.css' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/?a=b', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), foobarContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/?a=b', t => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'HEAD', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), '') | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/not-defined', (t) => { | ||
|  |       t.plan(3) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/not-defined' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.same(JSON.parse(body), { hello: 'world' }) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/deep/path/for/test/purpose/', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/deep/path/for/test/purpose/' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), deepContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/deep/path/for/test/', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/deep/path/for/test/' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), innerIndex) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/deep/path/for/test/', t => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'HEAD', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/deep/path/for/test/' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), '') | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/../index.js', (t) => { | ||
|  |       t.plan(3) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/../index.js', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.same(JSON.parse(body), { hello: 'world' }) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('register /static with wildcard false and alternative index', t => { | ||
|  |   t.plan(11) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static', | ||
|  |     wildcard: false, | ||
|  |     index: ['foobar.html', 'foo.html', 'index.html'] | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   fastify.get('/*', (request, reply) => { | ||
|  |     reply.send({ hello: 'world' }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/static/index.html', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/index.html', t => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'HEAD', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), '') | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/index.css', (t) => { | ||
|  |       t.plan(2 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/index.css' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static', (t) => { | ||
|  |       t.plan(2) | ||
|  | 
 | ||
|  |       // simple-get doesn't tell us about redirects so use http.request directly
 | ||
|  |       // to verify we do not get a redirect when not requested
 | ||
|  |       const testurl = 'http://localhost:' + fastify.server.address().port + '/static' | ||
|  |       const req = http.request(url.parse(testurl), res => { | ||
|  |         t.equal(res.statusCode, 200) | ||
|  |         let body = '' | ||
|  |         res.on('data', (chunk) => { | ||
|  |           body += chunk.toString() | ||
|  |         }) | ||
|  |         res.on('end', () => { | ||
|  |           t.same(JSON.parse(body.toString()), { hello: 'world' }) | ||
|  |         }) | ||
|  |       }) | ||
|  |       req.on('error', (err) => console.error(err)) | ||
|  |       req.end() | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), foobarContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/', t => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'HEAD', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), '') | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/not-defined', (t) => { | ||
|  |       t.plan(3) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/not-defined' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.same(JSON.parse(body), { hello: 'world' }) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/deep/path/for/test/purpose/', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/deep/path/for/test/purpose/' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), deepContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/deep/path/for/test/', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/deep/path/for/test/' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), innerIndex) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/../index.js', (t) => { | ||
|  |       t.plan(3) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/../index.js', | ||
|  |         followRedirect: false | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.same(JSON.parse(body), { hello: 'world' }) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('register /static with redirect true', t => { | ||
|  |   t.plan(7) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static', | ||
|  |     redirect: true, | ||
|  |     index: 'index.html' | ||
|  |   } | ||
|  | 
 | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(3001, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/static?a=b', (t) => { | ||
|  |       t.plan(5 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  | 
 | ||
|  |       // simple-get doesn't tell us about redirects so use http.request directly
 | ||
|  |       const testurl = 'http://localhost:' + fastify.server.address().port + '/static?a=b' | ||
|  |       const req = http.request(url.parse(testurl), res => { | ||
|  |         t.equal(res.statusCode, 301) | ||
|  |         t.equal(res.headers.location, '/static/?a=b') | ||
|  |       }) | ||
|  |       req.on('error', (err) => console.error(err)) | ||
|  |       req.end() | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static?a=b' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static', t => { | ||
|  |       t.plan(2) | ||
|  | 
 | ||
|  |       // simple-get doesn't tell us about redirects so use http.request directly
 | ||
|  |       const testurl = 'http://localhost:' + fastify.server.address().port + '/static' | ||
|  |       const req = http.request(url.parse(testurl), res => { | ||
|  |         t.equal(res.statusCode, 301) | ||
|  |         t.equal(res.headers.location, '/static/') | ||
|  |       }) | ||
|  |       req.on('error', err => console.error(err)) | ||
|  |       req.end() | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/', t => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/deep', (t) => { | ||
|  |       t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT) | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/deep' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |         genericErrorResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/deep/path/for/test?a=b', (t) => { | ||
|  |       t.plan(5 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  | 
 | ||
|  |       // simple-get doesn't tell us about redirects so use http.request directly
 | ||
|  |       const testurl = 'http://localhost:' + fastify.server.address().port + '/static/deep/path/for/test?a=b' | ||
|  |       const req = http.request(url.parse(testurl), res => { | ||
|  |         t.equal(res.statusCode, 301) | ||
|  |         t.equal(res.headers.location, '/static/deep/path/for/test/?a=b') | ||
|  |       }) | ||
|  |       req.on('error', (err) => console.error(err)) | ||
|  |       req.end() | ||
|  | 
 | ||
|  |       // verify the redirect with query parameters works
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: testurl | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), innerIndex) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/deep/path/for/test', (t) => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/deep/path/for/test' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), innerIndex) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('register /static with redirect true and wildcard false', t => { | ||
|  |   t.plan(8) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static', | ||
|  |     redirect: true, | ||
|  |     wildcard: false, | ||
|  |     index: 'index.html' | ||
|  |   } | ||
|  | 
 | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(3001, err => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/static?a=b', t => { | ||
|  |       t.plan(5 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  | 
 | ||
|  |       // simple-get doesn't tell us about redirects so use http.request directly
 | ||
|  |       const testurl = 'http://localhost:' + fastify.server.address().port + '/static?a=b' | ||
|  |       const req = http.request(url.parse(testurl), res => { | ||
|  |         t.equal(res.statusCode, 301) | ||
|  |         t.equal(res.headers.location, '/static/?a=b') | ||
|  |       }) | ||
|  |       req.on('error', err => console.error(err)) | ||
|  |       req.end() | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static?a=b' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/?a=b', t => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/?a=b' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/?a=b', t => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'HEAD', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/?a=b' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), '') | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/deep', t => { | ||
|  |       t.plan(2 + GENERIC_ERROR_RESPONSE_CHECK_COUNT) | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/deep' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |         genericErrorResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/deep/path/for/test?a=b', t => { | ||
|  |       t.plan(5 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  | 
 | ||
|  |       // simple-get doesn't tell us about redirects so use http.request directly
 | ||
|  |       const testurl = 'http://localhost:' + fastify.server.address().port + '/static/deep/path/for/test?a=b' | ||
|  |       const req = http.request(url.parse(testurl), res => { | ||
|  |         t.equal(res.statusCode, 301) | ||
|  |         t.equal(res.headers.location, '/static/deep/path/for/test/?a=b') | ||
|  |       }) | ||
|  |       req.on('error', err => console.error(err)) | ||
|  |       req.end() | ||
|  | 
 | ||
|  |       // verify the redirect with query parameters works
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: testurl | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), innerIndex) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/deep/path/for/test', t => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/deep/path/for/test' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), innerIndex) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/deep/path/for/test', t => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'HEAD', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/deep/path/for/test' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), '') | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('trailing slash behavior with redirect = false', (t) => { | ||
|  |   t.plan(6) | ||
|  | 
 | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static', | ||
|  |     redirect: false | ||
|  |   }) | ||
|  |   fastify.server.unref() | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     const host = 'http://localhost:' + fastify.server.address().port | ||
|  | 
 | ||
|  |     t.test('prefix with no trailing slash => 404', (t) => { | ||
|  |       t.plan(2) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: host + '/static' | ||
|  |       }, (err, response) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('prefix with trailing trailing slash => 200', (t) => { | ||
|  |       t.plan(2) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: host + '/static/' | ||
|  |       }, (err, response) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('deep path with no index.html or trailing slash => 404', (t) => { | ||
|  |       t.plan(2) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: host + '/static/deep/path' | ||
|  |       }, (err, response) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('deep path with index.html but no trailing slash => 200', (t) => { | ||
|  |       t.plan(2) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: host + '/static/deep/path/for/test' | ||
|  |       }, (err, response) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('deep path with index.html and trailing slash => 200', (t) => { | ||
|  |       t.plan(2) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: host + '/static/deep/path/for/test/' | ||
|  |       }, (err, response) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('if dotfiles are properly served according to plugin options', (t) => { | ||
|  |   t.plan(3) | ||
|  |   const exampleContents = fs | ||
|  |     .readFileSync(path.join(__dirname, 'static', '.example'), { | ||
|  |       encoding: 'utf8' | ||
|  |     }) | ||
|  |     .toString() | ||
|  | 
 | ||
|  |   t.test('freely serve dotfiles', (t) => { | ||
|  |     t.plan(4) | ||
|  |     const fastify = Fastify() | ||
|  | 
 | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, 'static'), | ||
|  |       prefix: '/static/', | ||
|  |       dotfiles: 'allow' | ||
|  |     } | ||
|  | 
 | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  |     fastify.listen(0, (err) => { | ||
|  |       t.error(err) | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/.example' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), exampleContents) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.test('ignore dotfiles', (t) => { | ||
|  |     t.plan(3) | ||
|  |     const fastify = Fastify() | ||
|  | 
 | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, 'static'), | ||
|  |       prefix: '/static/', | ||
|  |       dotfiles: 'ignore' | ||
|  |     } | ||
|  | 
 | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  |     fastify.listen(0, (err) => { | ||
|  |       t.error(err) | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/.example' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 404) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.test('deny requests to serve a dotfile', (t) => { | ||
|  |     t.plan(3) | ||
|  |     const fastify = Fastify() | ||
|  | 
 | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, 'static'), | ||
|  |       prefix: '/static/', | ||
|  |       dotfiles: 'deny' | ||
|  |     } | ||
|  | 
 | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  |     fastify.listen(0, (err) => { | ||
|  |       t.error(err) | ||
|  | 
 | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/static/.example' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 403) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('register with failing glob handler', (t) => { | ||
|  |   const fastifyStatic = proxyquire.noCallThru()('../', { | ||
|  |     glob: function globStub (pattern, options, cb) { | ||
|  |       process.nextTick(function () { | ||
|  |         return cb(new Error('mock glob error')) | ||
|  |       }) | ||
|  |     } | ||
|  |   }) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     serve: true, | ||
|  |     wildcard: false | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     fastify.server.unref() | ||
|  |     t.ok(err) | ||
|  |     t.end() | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test( | ||
|  |   'register with rootpath that causes statSync to fail with non-ENOENT code', | ||
|  |   (t) => { | ||
|  |     const fastifyStatic = proxyquire('../', { | ||
|  |       fs: { | ||
|  |         statSync: function statSyncStub (path) { | ||
|  |           throw new Error({ code: 'MOCK' }) | ||
|  |         } | ||
|  |       } | ||
|  |     }) | ||
|  | 
 | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, '/static'), | ||
|  |       wildcard: true | ||
|  |     } | ||
|  |     const fastify = Fastify() | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  |     fastify.listen(0, (err) => { | ||
|  |       fastify.server.unref() | ||
|  |       t.ok(err) | ||
|  |       t.end() | ||
|  |     }) | ||
|  |   } | ||
|  | ) | ||
|  | 
 | ||
|  | t.test('inject support', async (t) => { | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static' | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   const response = await fastify.inject({ | ||
|  |     method: 'GET', | ||
|  |     url: '/static/index.html' | ||
|  |   }) | ||
|  |   t.equal(response.statusCode, 200) | ||
|  |   t.equal(response.body.toString(), indexContent) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('routes should use custom errorHandler premature stream close', t => { | ||
|  |   t.plan(4) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static/' | ||
|  |   } | ||
|  | 
 | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.addHook('onRoute', function (routeOptions) { | ||
|  |     t.ok(routeOptions.errorHandler instanceof Function) | ||
|  | 
 | ||
|  |     routeOptions.onRequest = (request, reply, done) => { | ||
|  |       const fakeError = new Error() | ||
|  |       fakeError.code = 'ERR_STREAM_PREMATURE_CLOSE' | ||
|  |       done(fakeError) | ||
|  |     } | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.inject( | ||
|  |     { | ||
|  |       method: 'GET', | ||
|  |       url: '/static/index.html' | ||
|  |     }, | ||
|  |     (err, response) => { | ||
|  |       t.error(err) | ||
|  |       t.equal(response, null) | ||
|  |     } | ||
|  |   ) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('routes should fallback to default errorHandler', t => { | ||
|  |   t.plan(4) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static/' | ||
|  |   } | ||
|  | 
 | ||
|  |   const fastify = Fastify() | ||
|  | 
 | ||
|  |   fastify.addHook('onRoute', function (routeOptions) { | ||
|  |     t.ok(routeOptions.errorHandler instanceof Function) | ||
|  | 
 | ||
|  |     routeOptions.preHandler = (request, reply, done) => { | ||
|  |       const fakeError = new Error() | ||
|  |       fakeError.code = 'SOMETHING_ELSE' | ||
|  |       done(fakeError) | ||
|  |     } | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.inject({ | ||
|  |     method: 'GET', | ||
|  |     url: '/static/index.html' | ||
|  |   }, (err, response) => { | ||
|  |     t.error(err) | ||
|  |     t.same(JSON.parse(response.payload), { | ||
|  |       statusCode: 500, | ||
|  |       code: 'SOMETHING_ELSE', | ||
|  |       error: 'Internal Server Error', | ||
|  |       message: '' | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('routes use default errorHandler when fastify.errorHandler is not defined', t => { | ||
|  |   t.plan(4) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     prefix: '/static/' | ||
|  |   } | ||
|  | 
 | ||
|  |   const fastify = Fastify() | ||
|  |   fastify[kErrorHandler] = undefined // simulate old fastify version
 | ||
|  | 
 | ||
|  |   fastify.addHook('onRoute', function (routeOptions) { | ||
|  |     t.notOk(routeOptions.errorHandler instanceof Function) | ||
|  | 
 | ||
|  |     routeOptions.preHandler = (request, reply, done) => { | ||
|  |       const fakeError = new Error() | ||
|  |       fakeError.code = 'SOMETHING_ELSE' | ||
|  |       done(fakeError) | ||
|  |     } | ||
|  |   }) | ||
|  | 
 | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.inject({ | ||
|  |     method: 'GET', | ||
|  |     url: '/static/index.html' | ||
|  |   }, (err, response) => { | ||
|  |     t.error(err) | ||
|  |     t.same(JSON.parse(response.payload), { | ||
|  |       statusCode: 500, | ||
|  |       code: 'SOMETHING_ELSE', | ||
|  |       error: 'Internal Server Error', | ||
|  |       message: '' | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('precent encoded URLs in glob mode', (t) => { | ||
|  |   t.plan(4) | ||
|  | 
 | ||
|  |   const fastify = Fastify({}) | ||
|  | 
 | ||
|  |   fastify.register(fastifyStatic, { | ||
|  |     root: path.join(__dirname, 'static'), | ||
|  |     prefix: '/static', | ||
|  |     wildcard: true | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, (err) => { | ||
|  |     t.error(err) | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     simple.concat({ | ||
|  |       method: 'GET', | ||
|  |       url: 'http://localhost:' + fastify.server.address().port + '/static/a .md', | ||
|  |       followRedirect: false | ||
|  |     }, (err, response, body) => { | ||
|  |       t.error(err) | ||
|  |       t.equal(response.statusCode, 200) | ||
|  |       t.equal( | ||
|  |         fs.readFileSync(path.join(__dirname, 'static', 'a .md'), 'utf-8'), | ||
|  |         body.toString() | ||
|  |       ) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('register /static and /static2 without wildcard', t => { | ||
|  |   t.plan(3) | ||
|  | 
 | ||
|  |   const pluginOptions = { | ||
|  |     root: [path.join(__dirname, '/static'), path.join(__dirname, '/static2')], | ||
|  |     wildcard: false | ||
|  |   } | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, pluginOptions) | ||
|  | 
 | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |   fastify.listen(0, err => { | ||
|  |     t.error(err) | ||
|  | 
 | ||
|  |     fastify.server.unref() | ||
|  | 
 | ||
|  |     t.test('/index.html', t => { | ||
|  |       t.plan(4 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/index.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.not(body.toString(), index2Content) | ||
|  |         t.equal(body.toString(), indexContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.test('/static/bar.html', t => { | ||
|  |       t.plan(3 + GENERIC_RESPONSE_CHECK_COUNT) | ||
|  |       simple.concat({ | ||
|  |         method: 'GET', | ||
|  |         url: 'http://localhost:' + fastify.server.address().port + '/bar.html' | ||
|  |       }, (err, response, body) => { | ||
|  |         t.error(err) | ||
|  |         t.equal(response.statusCode, 200) | ||
|  |         t.equal(body.toString(), barContent) | ||
|  |         genericResponseChecks(t, response) | ||
|  |       }) | ||
|  |     }) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test( | ||
|  |   'will serve pre-compressed files with .br at the highest priority', | ||
|  |   async (t) => { | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, '/static-pre-compressed'), | ||
|  |       prefix: '/static-pre-compressed/', | ||
|  |       preCompressed: true | ||
|  |     } | ||
|  | 
 | ||
|  |     const fastify = Fastify() | ||
|  | 
 | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |     const response = await fastify.inject({ | ||
|  |       method: 'GET', | ||
|  |       url: '/static-pre-compressed/all-three.html', | ||
|  |       headers: { | ||
|  |         'accept-encoding': 'gzip, deflate, br' | ||
|  |       } | ||
|  |     }) | ||
|  | 
 | ||
|  |     genericResponseChecks(t, response) | ||
|  |     t.equal(response.headers['content-encoding'], 'br') | ||
|  |     t.equal(response.statusCode, 200) | ||
|  |     t.same(response.rawPayload, allThreeBr) | ||
|  |     t.end() | ||
|  |   } | ||
|  | ) | ||
|  | 
 | ||
|  | t.test( | ||
|  |   'will serve pre-compressed files and fallback to .gz if .br is not on disk', | ||
|  |   async (t) => { | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, '/static-pre-compressed'), | ||
|  |       prefix: '/static-pre-compressed/', | ||
|  |       preCompressed: true | ||
|  |     } | ||
|  | 
 | ||
|  |     const fastify = Fastify() | ||
|  | 
 | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |     const response = await fastify.inject({ | ||
|  |       method: 'GET', | ||
|  |       url: '/static-pre-compressed/gzip-only.html', | ||
|  |       headers: { | ||
|  |         'accept-encoding': 'gzip, deflate, br' | ||
|  |       } | ||
|  |     }) | ||
|  | 
 | ||
|  |     genericResponseChecks(t, response) | ||
|  |     t.equal(response.headers['content-encoding'], 'gzip') | ||
|  |     t.equal(response.statusCode, 200) | ||
|  |     t.same(response.rawPayload, gzipOnly) | ||
|  |     t.end() | ||
|  |   } | ||
|  | ) | ||
|  | 
 | ||
|  | t.test( | ||
|  |   'will serve pre-compressed files with .gzip if * directive used', | ||
|  |   async (t) => { | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, '/static-pre-compressed'), | ||
|  |       prefix: '/static-pre-compressed/', | ||
|  |       preCompressed: true | ||
|  |     } | ||
|  | 
 | ||
|  |     const fastify = Fastify() | ||
|  | 
 | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |     const response = await fastify.inject({ | ||
|  |       method: 'GET', | ||
|  |       url: '/static-pre-compressed/all-three.html', | ||
|  |       headers: { | ||
|  |         'accept-encoding': '*' | ||
|  |       } | ||
|  |     }) | ||
|  | 
 | ||
|  |     genericResponseChecks(t, response) | ||
|  |     t.equal(response.headers['content-encoding'], 'gzip') | ||
|  |     t.equal(response.statusCode, 200) | ||
|  |     t.same(response.rawPayload, allThreeGzip) | ||
|  |     t.end() | ||
|  |   } | ||
|  | ) | ||
|  | 
 | ||
|  | t.test( | ||
|  |   'will serve pre-compressed files with .gzip if multiple * directives used', | ||
|  |   async (t) => { | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, '/static-pre-compressed'), | ||
|  |       prefix: '/static-pre-compressed/', | ||
|  |       preCompressed: true | ||
|  |     } | ||
|  | 
 | ||
|  |     const fastify = Fastify() | ||
|  | 
 | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |     const response = await fastify.inject({ | ||
|  |       method: 'GET', | ||
|  |       url: '/static-pre-compressed/all-three.html', | ||
|  |       headers: { | ||
|  |         'accept-encoding': '*, *' | ||
|  |       } | ||
|  |     }) | ||
|  | 
 | ||
|  |     genericResponseChecks(t, response) | ||
|  |     t.equal(response.headers['content-encoding'], 'gzip') | ||
|  |     t.equal(response.statusCode, 200) | ||
|  |     t.same(response.rawPayload, allThreeGzip) | ||
|  |     t.end() | ||
|  |   } | ||
|  | ) | ||
|  | 
 | ||
|  | t.test( | ||
|  |   'will serve uncompressed files if there are no compressed variants on disk', | ||
|  |   async (t) => { | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, '/static-pre-compressed'), | ||
|  |       prefix: '/static-pre-compressed/', | ||
|  |       preCompressed: true | ||
|  |     } | ||
|  | 
 | ||
|  |     const fastify = Fastify() | ||
|  | 
 | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |     const response = await fastify.inject({ | ||
|  |       method: 'GET', | ||
|  |       url: '/static-pre-compressed/uncompressed.html', | ||
|  |       headers: { | ||
|  |         'accept-encoding': 'gzip, deflate, br' | ||
|  |       } | ||
|  |     }) | ||
|  | 
 | ||
|  |     genericResponseChecks(t, response) | ||
|  |     t.equal(response.headers['content-encoding'], undefined) | ||
|  |     t.equal(response.statusCode, 200) | ||
|  |     t.equal(response.body, uncompressedStatic) | ||
|  |     t.end() | ||
|  |   } | ||
|  | ) | ||
|  | 
 | ||
|  | t.test( | ||
|  |   'will serve pre-compressed files with .br at the highest priority (with wildcard: false)', | ||
|  |   async (t) => { | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, '/static-pre-compressed'), | ||
|  |       prefix: '/static-pre-compressed/', | ||
|  |       preCompressed: true, | ||
|  |       wildcard: false | ||
|  |     } | ||
|  | 
 | ||
|  |     const fastify = Fastify() | ||
|  | 
 | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |     const response = await fastify.inject({ | ||
|  |       method: 'GET', | ||
|  |       url: '/static-pre-compressed/all-three.html', | ||
|  |       headers: { | ||
|  |         'accept-encoding': 'gzip, deflate, br' | ||
|  |       } | ||
|  |     }) | ||
|  | 
 | ||
|  |     genericResponseChecks(t, response) | ||
|  |     t.equal(response.headers['content-encoding'], 'br') | ||
|  |     t.equal(response.statusCode, 200) | ||
|  |     t.same(response.rawPayload, allThreeBr) | ||
|  |     t.end() | ||
|  |   } | ||
|  | ) | ||
|  | 
 | ||
|  | t.test( | ||
|  |   'will serve pre-compressed files and fallback to .gz if .br is not on disk (with wildcard: false)', | ||
|  |   async (t) => { | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, '/static-pre-compressed'), | ||
|  |       prefix: '/static-pre-compressed/', | ||
|  |       preCompressed: true, | ||
|  |       wildcard: false | ||
|  |     } | ||
|  | 
 | ||
|  |     const fastify = Fastify() | ||
|  | 
 | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |     const response = await fastify.inject({ | ||
|  |       method: 'GET', | ||
|  |       url: '/static-pre-compressed/gzip-only.html', | ||
|  |       headers: { | ||
|  |         'accept-encoding': 'gzip, deflate, br' | ||
|  |       } | ||
|  |     }) | ||
|  | 
 | ||
|  |     genericResponseChecks(t, response) | ||
|  |     t.equal(response.headers['content-encoding'], 'gzip') | ||
|  |     t.equal(response.statusCode, 200) | ||
|  |     t.same(response.rawPayload, gzipOnly) | ||
|  |     t.end() | ||
|  |   } | ||
|  | ) | ||
|  | 
 | ||
|  | t.test( | ||
|  |   'will serve pre-compressed files with .gzip if * directive used (with wildcard: false)', | ||
|  |   async (t) => { | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, '/static-pre-compressed'), | ||
|  |       prefix: '/static-pre-compressed/', | ||
|  |       preCompressed: true, | ||
|  |       wildcard: false | ||
|  |     } | ||
|  | 
 | ||
|  |     const fastify = Fastify() | ||
|  | 
 | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |     const response = await fastify.inject({ | ||
|  |       method: 'GET', | ||
|  |       url: '/static-pre-compressed/all-three.html', | ||
|  |       headers: { | ||
|  |         'accept-encoding': '*' | ||
|  |       } | ||
|  |     }) | ||
|  | 
 | ||
|  |     genericResponseChecks(t, response) | ||
|  |     t.equal(response.headers['content-encoding'], 'gzip') | ||
|  |     t.equal(response.statusCode, 200) | ||
|  |     t.same(response.rawPayload, allThreeGzip) | ||
|  |     t.end() | ||
|  |   } | ||
|  | ) | ||
|  | 
 | ||
|  | t.test( | ||
|  |   'will serve pre-compressed files with .gzip if multiple * directives used (with wildcard: false)', | ||
|  |   async (t) => { | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, '/static-pre-compressed'), | ||
|  |       prefix: '/static-pre-compressed/', | ||
|  |       preCompressed: true, | ||
|  |       wildcard: false | ||
|  |     } | ||
|  | 
 | ||
|  |     const fastify = Fastify() | ||
|  | 
 | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |     const response = await fastify.inject({ | ||
|  |       method: 'GET', | ||
|  |       url: '/static-pre-compressed/all-three.html', | ||
|  |       headers: { | ||
|  |         'accept-encoding': '*, *' | ||
|  |       } | ||
|  |     }) | ||
|  | 
 | ||
|  |     genericResponseChecks(t, response) | ||
|  |     t.equal(response.headers['content-encoding'], 'gzip') | ||
|  |     t.equal(response.statusCode, 200) | ||
|  |     t.same(response.rawPayload, allThreeGzip) | ||
|  |     t.end() | ||
|  |   } | ||
|  | ) | ||
|  | 
 | ||
|  | t.test( | ||
|  |   'will serve uncompressed files if there are no compressed variants on disk (with wildcard: false)', | ||
|  |   async (t) => { | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, '/static-pre-compressed'), | ||
|  |       prefix: '/static-pre-compressed/', | ||
|  |       preCompressed: true, | ||
|  |       wildcard: false | ||
|  |     } | ||
|  | 
 | ||
|  |     const fastify = Fastify() | ||
|  | 
 | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |     const response = await fastify.inject({ | ||
|  |       method: 'GET', | ||
|  |       url: '/static-pre-compressed/uncompressed.html', | ||
|  |       headers: { | ||
|  |         'accept-encoding': 'gzip, deflate, br' | ||
|  |       } | ||
|  |     }) | ||
|  | 
 | ||
|  |     genericResponseChecks(t, response) | ||
|  |     t.equal(response.headers['content-encoding'], undefined) | ||
|  |     t.equal(response.statusCode, 200) | ||
|  |     t.equal(response.body, uncompressedStatic) | ||
|  |     t.end() | ||
|  |   } | ||
|  | ) | ||
|  | 
 | ||
|  | t.test( | ||
|  |   'will serve uncompressed files the accept-encoding header is missing', | ||
|  |   async (t) => { | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, '/static-pre-compressed'), | ||
|  |       prefix: '/static-pre-compressed/', | ||
|  |       preCompressed: true | ||
|  |     } | ||
|  | 
 | ||
|  |     const fastify = Fastify() | ||
|  | 
 | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |     const response = await fastify.inject({ | ||
|  |       method: 'GET', | ||
|  |       url: '/static-pre-compressed/uncompressed.html' | ||
|  |     }) | ||
|  | 
 | ||
|  |     genericResponseChecks(t, response) | ||
|  |     t.equal(response.headers['content-encoding'], undefined) | ||
|  |     t.equal(response.statusCode, 200) | ||
|  |     t.equal(response.body, uncompressedStatic) | ||
|  |     t.end() | ||
|  |   } | ||
|  | ) | ||
|  | 
 | ||
|  | t.test( | ||
|  |   'will serve precompressed index', | ||
|  |   async (t) => { | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, '/static-pre-compressed'), | ||
|  |       prefix: '/static-pre-compressed/', | ||
|  |       preCompressed: true | ||
|  |     } | ||
|  | 
 | ||
|  |     const fastify = Fastify() | ||
|  | 
 | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |     const response = await fastify.inject({ | ||
|  |       method: 'GET', | ||
|  |       url: '/static-pre-compressed/', | ||
|  |       headers: { | ||
|  |         'accept-encoding': 'gzip, deflate, br' | ||
|  |       } | ||
|  |     }) | ||
|  | 
 | ||
|  |     genericResponseChecks(t, response) | ||
|  |     t.equal(response.headers['content-encoding'], 'br') | ||
|  |     t.equal(response.statusCode, 200) | ||
|  |     t.same(response.rawPayload, indexBr) | ||
|  |     t.end() | ||
|  |   } | ||
|  | ) | ||
|  | 
 | ||
|  | t.test( | ||
|  |   'will serve preCompressed index without trailing slash', | ||
|  |   async (t) => { | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, '/static-pre-compressed'), | ||
|  |       prefix: '/static-pre-compressed/', | ||
|  |       preCompressed: true, | ||
|  |       redirect: false | ||
|  |     } | ||
|  | 
 | ||
|  |     const fastify = Fastify() | ||
|  | 
 | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |     const response = await fastify.inject({ | ||
|  |       method: 'GET', | ||
|  |       url: '/static-pre-compressed/dir', | ||
|  |       headers: { | ||
|  |         'accept-encoding': 'gzip, deflate, br' | ||
|  |       } | ||
|  |     }) | ||
|  | 
 | ||
|  |     genericResponseChecks(t, response) | ||
|  |     t.equal(response.headers['content-encoding'], 'br') | ||
|  |     t.equal(response.statusCode, 200) | ||
|  |     t.same(response.rawPayload, dirIndexBr) | ||
|  |     t.end() | ||
|  |   } | ||
|  | ) | ||
|  | 
 | ||
|  | t.test( | ||
|  |   'will serve precompressed index with alternative index option', | ||
|  |   async (t) => { | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, '/static-pre-compressed'), | ||
|  |       prefix: '/static-pre-compressed/', | ||
|  |       preCompressed: true, | ||
|  |       index: ['all-three.html'] | ||
|  |     } | ||
|  | 
 | ||
|  |     const fastify = Fastify() | ||
|  | 
 | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |     const response = await fastify.inject({ | ||
|  |       method: 'GET', | ||
|  |       url: '/static-pre-compressed/', | ||
|  |       headers: { | ||
|  |         'accept-encoding': 'gzip, deflate, br' | ||
|  |       } | ||
|  |     }) | ||
|  | 
 | ||
|  |     genericResponseChecks(t, response) | ||
|  |     t.equal(response.headers['content-encoding'], 'br') | ||
|  |     t.equal(response.statusCode, 200) | ||
|  |     t.same(response.rawPayload, allThreeBr) | ||
|  |     t.end() | ||
|  |   } | ||
|  | ) | ||
|  | 
 | ||
|  | t.test( | ||
|  |   'will serve precompressed file without content-type charset', | ||
|  |   async (t) => { | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, '/static-pre-compressed'), | ||
|  |       prefix: '/static-pre-compressed/', | ||
|  |       preCompressed: true | ||
|  |     } | ||
|  | 
 | ||
|  |     const fastify = Fastify() | ||
|  | 
 | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |     const response = await fastify.inject({ | ||
|  |       method: 'GET', | ||
|  |       url: '/static-pre-compressed/sample.jpg', | ||
|  |       headers: { | ||
|  |         'accept-encoding': 'gzip, deflate, br' | ||
|  |       } | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.equal(response.headers['content-type'], 'image/jpeg') | ||
|  |     t.equal(response.headers['content-encoding'], 'br') | ||
|  |     t.equal(response.statusCode, 200) | ||
|  |     t.end() | ||
|  |   } | ||
|  | ) | ||
|  | 
 | ||
|  | t.test( | ||
|  |   'nonexistent index with precompressed option', | ||
|  |   async (t) => { | ||
|  |     const pluginOptions = { | ||
|  |       root: path.join(__dirname, '/static-pre-compressed'), | ||
|  |       prefix: '/static-pre-compressed/', | ||
|  |       preCompressed: true | ||
|  |     } | ||
|  | 
 | ||
|  |     const fastify = Fastify() | ||
|  | 
 | ||
|  |     fastify.register(fastifyStatic, pluginOptions) | ||
|  |     t.teardown(fastify.close.bind(fastify)) | ||
|  | 
 | ||
|  |     const response = await fastify.inject({ | ||
|  |       method: 'GET', | ||
|  |       url: '/static-pre-compressed/empty/', | ||
|  |       headers: { | ||
|  |         'accept-encoding': 'gzip, deflate, br' | ||
|  |       } | ||
|  |     }) | ||
|  | 
 | ||
|  |     t.equal(response.statusCode, 404) | ||
|  |     genericErrorResponseChecks(t, response) | ||
|  |     t.end() | ||
|  |   } | ||
|  | ) | ||
|  | 
 | ||
|  | t.test('should not redirect to protocol-relative locations', (t) => { | ||
|  |   const urls = [ | ||
|  |     ['//^/..', '/', 301], | ||
|  |     ['//^/.', null, 404], // it is NOT recognized as a directory by pillarjs/send
 | ||
|  |     ['//:/..', '/', 301], | ||
|  |     ['/\\\\a//google.com/%2e%2e%2f%2e%2e', '/a//google.com/%2e%2e%2f%2e%2e/', 301], | ||
|  |     ['//a//youtube.com/%2e%2e%2f%2e%2e', '/a//youtube.com/%2e%2e%2f%2e%2e/', 301], | ||
|  |     ['/^', null, 404], // it is NOT recognized as a directory by pillarjs/send
 | ||
|  |     ['//google.com/%2e%2e', '/', 301], | ||
|  |     ['//users/%2e%2e', '/', 301], | ||
|  |     ['//users', null, 404], | ||
|  |     ['///deep/path//for//test//index.html', null, 200] | ||
|  |   ] | ||
|  | 
 | ||
|  |   t.plan(1 + urls.length * 2) | ||
|  |   const fastify = Fastify() | ||
|  |   fastify.register(fastifyStatic, { | ||
|  |     root: path.join(__dirname, '/static'), | ||
|  |     redirect: true | ||
|  |   }) | ||
|  |   t.teardown(fastify.close.bind(fastify)) | ||
|  |   fastify.listen(0, (err, address) => { | ||
|  |     t.error(err) | ||
|  |     urls.forEach(([testUrl, expected, status]) => { | ||
|  |       const req = http.request(url.parse(address + testUrl), res => { | ||
|  |         t.equal(res.statusCode, status, `status ${testUrl}`) | ||
|  | 
 | ||
|  |         if (expected) { | ||
|  |           t.equal(res.headers.location, expected) | ||
|  |         } else { | ||
|  |           t.notOk(res.headers.location) | ||
|  |         } | ||
|  |       }) | ||
|  |       req.on('error', t.error) | ||
|  |       req.end() | ||
|  |     }) | ||
|  |   }) | ||
|  | }) |