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
						
					
					
				| '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()
 | |
|     })
 | |
|   })
 | |
| })
 |