From 51c44373ebf2e0214bec2cb8a2136be018adf7b1 Mon Sep 17 00:00:00 2001 From: Evheniy Bystrov Date: Mon, 30 Oct 2017 15:52:54 +0200 Subject: [PATCH] updates --- .editorconfig | 10 + .eslintrc | 33 +-- .gitignore | 3 +- .travis.yml | 9 +- README.md | 32 ++- appveyor.yml | 6 +- index.js | 142 +++++------ lib/cacheCheck.js | 32 ++- lib/fileStream.js | 92 +++---- lib/getEncoding.js | 4 +- lib/getPath.js | 55 ++--- lib/getStats.js | 42 ++-- lib/getType.js | 9 +- lib/gzipFileStream.js | 117 ++++----- lib/methodCheck.js | 15 +- package.json | 57 ++--- tests/errors.js | 329 +++++++++++++------------ tests/index.js | 556 ++++++++++++++++++++++++------------------ 18 files changed, 824 insertions(+), 719 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..6fe4091 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true + +charset = utf-8 + +indent_style = space +indent_size = 2 diff --git a/.eslintrc b/.eslintrc index bc5a6d4..cecceef 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,22 +1,11 @@ -{ - "extends": "eslint", - "env": { - "es6": true, - "node": true, - "mocha": true - }, - "parserOptions": { - "ecmaVersion": 8, - "sourceType": "module" - }, - "rules": { - "indent": ["error", 4, {"SwitchCase": 1}], - "quotes": ["error", "single"], - "no-unused-expressions": 0, - "no-underscore-dangle": 0, - "func-style": [ - "error", - "declaration", { "allowArrowFunctions": true } - ] - } -} \ No newline at end of file +{ + "extends": "airbnb-base", + "env": { + "node": true, + "mocha": true + }, + "rules": { + "no-unused-expressions": 0, + "no-param-reassign": 0 + } +} diff --git a/.gitignore b/.gitignore index 6420e3e..cbde38c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ coverage npm-debug.log node_modules .DS_Store -logs/app.error.log \ No newline at end of file +logs/app.error.log +package-lock.json \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index bb0d1c5..d7b77ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,7 @@ language: node_js node_js: - - "7.6" - - "7.7" - - "7.8" - - "7.9" + - "7" + - "8" script: - - npm run lint - npm run test - - npm run report \ No newline at end of file + - npm run report diff --git a/README.md b/README.md index 7641113..d349349 100644 --- a/README.md +++ b/README.md @@ -29,21 +29,30 @@ YEPS Static file serving ## How to use const App = require('yeps'); + const serve = require('yeps-static'); + const error = require('yeps-error'); + const logger = require('yeps-logger'); + const server = require('yeps-server'); const app = new App(); app.all([ - serve(), error(), + logger(), + serve(), ]); + + server.createHttpServer(app); -Or with options: +Or with **options**: const { resolve } = require('path'); app.all([ + error(), + logger(), serve({ root: resolve(__dirname, 'public'), index: 'index.html', @@ -51,7 +60,6 @@ Or with options: gzip: true, maxage: 0, }), - error(), ]); #### With virtual host @@ -59,20 +67,28 @@ Or with options: const App = require('yeps'); const VirtualHost = require('yeps-virtual-host'); const Router = require('yeps-router'); + const error = require('yeps-error'); + const logger = require('yeps-logger'); + + const server = require('yeps-server'); const { resolve } = require('path'); const vhost = new VirtualHost(); const router = new Router(); + const serve = require('yeps-static'); const app = new App(); - app.then(error()); + app.all([ + error(), + logger(), + ]); - router.get('/').then(async ctx => { + router.get('/').then(async (ctx) => { ctx.res.statusCode = 200; ctx.res.setHeader('Content-Type', 'application/json'); ctx.res.end('{"status":"OK"}'); @@ -85,9 +101,11 @@ Or with options: vhost .http('static.yeps.info') .then(serve({ - root: resolve(__dirname, 'files') + root: resolve(__dirname, 'files'), })); app.then(vhost.resolve()); -#### [YEPS documentation](http://yeps.info/) \ No newline at end of file + server.createHttpServer(app); + +#### [YEPS documentation](http://yeps.info/) diff --git a/appveyor.yml b/appveyor.yml index 1a89ce0..9101e3f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,13 +1,13 @@ environment: matrix: - - nodejs_version: "7.7" + - nodejs_version: "8" install: - ps: Install-Product node $env:nodejs_version - npm install test_script: - node --version - npm --version - - npm run lint + - npm run test:lint - npm run test:security - npm run test:code -build: off \ No newline at end of file +build: off diff --git a/index.js b/index.js index 9e758eb..d74a900 100644 --- a/index.js +++ b/index.js @@ -1,68 +1,74 @@ -const debug = require('debug')('yeps:static:index'); - -const methodCheck = require('./lib/methodCheck'); -const cacheCheck = require('./lib/cacheCheck'); -const getPath = require('./lib/getPath'); -const getStats = require('./lib/getStats'); -const getType = require('./lib/getType'); -const getEncoding = require('./lib/getEncoding'); -const fileStream = require('./lib/fileStream'); -const gzipFileStream = require('./lib/gzipFileStream'); - -module.exports = ({root = __dirname, index = 'index.html', etag = true, gzip = true, maxage = 0} = {}) => async context => { - - debug('YEPS Static'); - debug('Headers: %O', context.req.headers); - - try { - await methodCheck(context.req.method.toUpperCase()); - await cacheCheck(etag, context); - let path = await getPath(root, index, context.req.url); - const type = getType(path); - const stats = await getStats(index, path); - path = stats.path; - const encoding = getEncoding(context.req.headers['accept-encoding']); - - if (etag) { - context.res.setHeader('ETag', context.req.url); - debug('ETag: %s', context.req.url); - } - - context.res.setHeader('Last-Modified', stats.mtime.toUTCString()); - debug('Last-Modified: %s', stats.mtime.toUTCString()); - - if (maxage) { - context.res.setHeader('Cache-Control', `max-age=${(maxage / 1000 | 0)}`); - debug('Cache-Control: %s', `max-age=${(maxage / 1000 | 0)}`); - } - - context.res.setHeader('Content-Type', type); - debug('Content-Type: %s', type); - - if (gzip) { - context.res.setHeader('Content-Encoding', encoding); - debug('Content-Encoding: %s', encoding); - } - - context.res.statusCode = 200; - - if (gzip) { - debug('gzip enabled!'); - debug('Encoding: %s', encoding); - - await gzipFileStream(path, context.res, encoding); - } else { - await fileStream(path, context.res); - } - } catch (error) { - debug('Error: %O', error); - - if (error && !['ENOENT', 'ENAMETOOLONG', 'ENOTDIR'].includes(error.code)) { - return Promise.reject(error); - } - - return Promise.resolve(); - } - - return Promise.reject(); -}; +const debug = require('debug')('yeps:static:index'); + +const methodCheck = require('./lib/methodCheck'); +const cacheCheck = require('./lib/cacheCheck'); +const getPath = require('./lib/getPath'); +const getStats = require('./lib/getStats'); +const getType = require('./lib/getType'); +const getEncoding = require('./lib/getEncoding'); +const fileStream = require('./lib/fileStream'); +const gzipFileStream = require('./lib/gzipFileStream'); + +module.exports = ({ + root = __dirname, + index = 'index.html', + etag = true, + gzip = true, + maxage = 0, +} = {}) => async (context) => { + debug('YEPS Static'); + debug('Headers: %O', context.req.headers); + + try { + await methodCheck(context.req.method.toUpperCase()); + await cacheCheck(etag, context); + const path = await getPath(root, index, context.req.url); + const stats = await getStats(index, path); + const newPath = stats.path; + const type = getType(newPath); + const encoding = getEncoding(context.req.headers['accept-encoding']); + + if (etag) { + context.res.setHeader('ETag', context.req.url); + debug('ETag: %s', context.req.url); + } + + context.res.setHeader('Last-Modified', stats.mtime.toUTCString()); + debug('Last-Modified: %s', stats.mtime.toUTCString()); + + if (maxage) { + const age = maxage / 1000; + context.res.setHeader('Cache-Control', `max-age=${age}`); + debug('Cache-Control: %s', `max-age=${age}`); + } + + context.res.setHeader('Content-Type', type); + debug('Content-Type: %s', type); + + if (gzip) { + context.res.setHeader('Content-Encoding', encoding); + debug('Content-Encoding: %s', encoding); + } + + context.res.statusCode = 200; + + if (gzip) { + debug('gzip enabled!'); + debug('Encoding: %s', encoding); + + await gzipFileStream(newPath, context.res, encoding); + } else { + await fileStream(newPath, context.res); + } + } catch (error) { + debug('Error: %O', error); + + if (error && !['ENOENT', 'ENAMETOOLONG', 'ENOTDIR'].includes(error.code)) { + return Promise.reject(error); + } + + return Promise.resolve(); + } + + return Promise.reject(); +}; diff --git a/lib/cacheCheck.js b/lib/cacheCheck.js index c489cde..c26566c 100644 --- a/lib/cacheCheck.js +++ b/lib/cacheCheck.js @@ -1,17 +1,15 @@ -const debug = require('debug')('yeps:static:cache'); - -module.exports = async (eTag, ctx) => { - - if (eTag && ctx.req.headers.etag) { - - ctx.res.statusCode = 304; - debug('ETag: %s', ctx.req.headers.etag); - - ctx.res.end(); - debug('End of response'); - - return Promise.reject(); - } - - return Promise.resolve(); -}; \ No newline at end of file +const debug = require('debug')('yeps:static:cache'); + +module.exports = async (eTag, ctx) => { + if (eTag && ctx.req.headers.etag) { + ctx.res.statusCode = 304; + debug('ETag: %s', ctx.req.headers.etag); + + ctx.res.end(); + debug('End of response'); + + return Promise.reject(); + } + + return Promise.resolve(); +}; diff --git a/lib/fileStream.js b/lib/fileStream.js index e34c36b..220e971 100644 --- a/lib/fileStream.js +++ b/lib/fileStream.js @@ -1,46 +1,46 @@ -const debug = require('debug')('yeps:static:file'); -const {createReadStream} = require('fs'); - -module.exports = (path, response) => new Promise((resolve, reject) => { - - const readStream = createReadStream(path); - - const wrongFlowHandle = error => { - debug(error); - readStream.destroy(); - response.statusCode = 500; - response.end(); - reject(error); - }; - - readStream.pipe(response); - - readStream.on('error', wrongFlowHandle); - - response - .on('error', wrongFlowHandle) - .on('close', wrongFlowHandle) - .on('finish', () => { - debug('finish'); - resolve(); - }); - - // for testing - if (global.yepsTestReadStream) { - debug('yepsTestReadStream'); - readStream.emit('error', new Error('Read stream test error')); - delete global.yepsTestReadStream; - } - - if (global.yepsTestResponseError) { - debug('yepsTestReyepsTestResponseErroradStream'); - response.emit('error', new Error('Response test error')); - delete global.yepsTestResponseError; - } - - if (global.yepsTestResponseClose) { - debug('yepsTestResponseClose'); - response.emit('close'); - delete global.yepsTestResponseClose; - } -}); +const debug = require('debug')('yeps:static:file'); +const { createReadStream } = require('fs'); + +module.exports = (path, response) => new Promise((resolve, reject) => { + debug(path); + const readStream = createReadStream(path); + + const wrongFlowHandle = (error) => { + debug(error); + readStream.destroy(); + response.statusCode = 500; + response.end(); + reject(error); + }; + + readStream.pipe(response); + + readStream.on('error', wrongFlowHandle); + + response + .on('error', wrongFlowHandle) + .on('close', wrongFlowHandle) + .on('finish', () => { + debug('finish'); + resolve(); + }); + + // for testing + if (global.yepsTestReadStream) { + debug('yepsTestReadStream'); + readStream.emit('error', new Error('Read stream test error')); + delete global.yepsTestReadStream; + } + + if (global.yepsTestResponseError) { + debug('yepsTestReyepsTestResponseErroradStream'); + response.emit('error', new Error('Response test error')); + delete global.yepsTestResponseError; + } + + if (global.yepsTestResponseClose) { + debug('yepsTestResponseClose'); + response.emit('close'); + delete global.yepsTestResponseClose; + } +}); diff --git a/lib/getEncoding.js b/lib/getEncoding.js index 36a5ece..b542ad9 100644 --- a/lib/getEncoding.js +++ b/lib/getEncoding.js @@ -1,3 +1 @@ -const debug = require('debug')('yeps:static:encoding'); - -module.exports = (contentEncoding = '') => contentEncoding.includes('deflate') ? 'deflate' : 'gzip'; +module.exports = (contentEncoding = '') => (contentEncoding.includes('deflate') ? 'deflate' : 'gzip'); diff --git a/lib/getPath.js b/lib/getPath.js index dc5a0b0..39dabc0 100644 --- a/lib/getPath.js +++ b/lib/getPath.js @@ -1,28 +1,27 @@ -const debug = require('debug')('yeps:static:path'); -const resolvePath = require('resolve-path'); -const { parse, normalize, resolve} = require('path'); - -module.exports = async (root, index, url) => { - - let path = url; - - path = path.substr(parse(path).root.length); - - path = decodeURIComponent(path); - debug('Path: %s', path); - - const trailingSlash = path[path.length - 1] === '/'; - - if (trailingSlash) { - path += index; - debug('Path: %s', path); - } - - const directory = normalize(resolve(root)); - debug('Directory: %s', directory); - - path = resolvePath(directory, path); - debug('Path: %s', path); - - return path; -}; \ No newline at end of file +const debug = require('debug')('yeps:static:path'); +const resolvePath = require('resolve-path'); +const { parse, normalize, resolve } = require('path'); + +module.exports = async (root, index, url) => { + let path = url; + + path = path.substr(parse(path).root.length); + + path = decodeURIComponent(path); + debug('Path: %s', path); + + const trailingSlash = path[path.length - 1] === '/'; + + if (trailingSlash) { + path += index; + debug('Path: %s', path); + } + + const directory = normalize(resolve(root)); + debug('Directory: %s', directory); + + path = resolvePath(directory, path); + debug('Path: %s', path); + + return path; +}; diff --git a/lib/getStats.js b/lib/getStats.js index 9f5795e..e95ff60 100644 --- a/lib/getStats.js +++ b/lib/getStats.js @@ -1,21 +1,21 @@ -const debug = require('debug')('yeps:static:stats'); -const { stat } = require('mz/fs'); -const { resolve } = require('path'); - -module.exports = async (index, path) => { - - let stats = await stat(path); - debug('Stats: %O', stats); - - if (stats.isDirectory()) { - path = resolve(path, index); - debug('Path: %s', path); - - stats = await stat(path); - debug('Stats: %O', stats); - } - - stats.path = path; - - return stats; -}; \ No newline at end of file +const debug = require('debug')('yeps:static:stats'); +const { stat } = require('mz/fs'); +const { resolve } = require('path'); + +module.exports = async (index, path) => { + let newPath = path; + let stats = await stat(newPath); + debug('Stats: %O', stats); + + if (stats.isDirectory()) { + newPath = resolve(newPath, index); + debug('Path: %s', newPath); + + stats = await stat(newPath); + debug('Stats: %O', stats); + } + + stats.path = newPath; + + return stats; +}; diff --git a/lib/getType.js b/lib/getType.js index affca0d..56a72b4 100644 --- a/lib/getType.js +++ b/lib/getType.js @@ -1,5 +1,4 @@ -const debug = require('debug')('yeps:static:type'); -const mime = require('mime-types'); -const { extname } = require('path'); - -module.exports = path => mime.contentType(extname(path)); +const mime = require('mime-types'); +const { extname } = require('path'); + +module.exports = path => mime.contentType(extname(path)); diff --git a/lib/gzipFileStream.js b/lib/gzipFileStream.js index 0d28bd6..40eee84 100644 --- a/lib/gzipFileStream.js +++ b/lib/gzipFileStream.js @@ -1,58 +1,59 @@ -const debug = require('debug')('yeps:static:gzip'); -const {createReadStream} = require('fs'); -const zlib = require('zlib'); - -module.exports = (path, response, encoding) => new Promise((resolve, reject) => { - - const zipStream = encoding === 'deflate' ? zlib.createDeflate() : zlib.createGzip(); - const readStream = createReadStream(path); - - const wrongFlowHandle = error => { - debug(error); - zipStream.end(); - readStream.destroy(); - response.statusCode = 500; - response.end(); - reject(error); - }; - - readStream.pipe(zipStream).pipe(response); - - readStream.on('error', wrongFlowHandle); - zipStream.on('error', wrongFlowHandle); - - response - .on('error', wrongFlowHandle) - .on('close', wrongFlowHandle) - .on('finish', () => { - debug('finish'); - resolve(); - }); - - - // for testing - if (global.yepsZipTestReadStream) { - debug('yepsZipTestReadStream'); - readStream.emit('error', new Error('Read stream test error')); - delete global.yepsZipTestReadStream; - } - - if (global.yepsZipTestZipStream) { - debug('yepsZipTestZipStream'); - zipStream.emit('error', new Error('Zip stream test error')); - delete global.yepsZipTestZipStream; - } - - if (global.yepsZipTestResponseError) { - debug('yepsZipTestResponseError'); - response.emit('error', new Error('Zip stream test error')); - delete global.yepsZipTestResponseError; - } - - if (global.yepsZipTestResponseClose) { - debug('yepsZipTestResponseClose'); - response.emit('close'); - delete global.yepsZipTestResponseClose; - } - -}); +const debug = require('debug')('yeps:static:gzip'); +const { createReadStream } = require('fs'); +const zlib = require('zlib'); + +module.exports = (path, response, encoding) => new Promise((resolve, reject) => { + debug(path); + debug(encoding); + + const zipStream = encoding === 'deflate' ? zlib.createDeflate() : zlib.createGzip(); + const readStream = createReadStream(path); + + const wrongFlowHandle = (error) => { + debug(error); + zipStream.end(); + readStream.destroy(); + response.statusCode = 500; + response.end(); + reject(error); + }; + + readStream.pipe(zipStream).pipe(response); + + readStream.on('error', wrongFlowHandle); + zipStream.on('error', wrongFlowHandle); + + response + .on('error', wrongFlowHandle) + .on('close', wrongFlowHandle) + .on('finish', () => { + debug('finish'); + resolve(); + }); + + + // for testing + if (global.yepsZipTestReadStream) { + debug('yepsZipTestReadStream'); + readStream.emit('error', new Error('Read stream test error')); + delete global.yepsZipTestReadStream; + } + + if (global.yepsZipTestZipStream) { + debug('yepsZipTestZipStream'); + zipStream.emit('error', new Error('Zip stream test error')); + delete global.yepsZipTestZipStream; + } + + if (global.yepsZipTestResponseError) { + debug('yepsZipTestResponseError'); + response.emit('error', new Error('Zip stream test error')); + delete global.yepsZipTestResponseError; + } + + if (global.yepsZipTestResponseClose) { + debug('yepsZipTestResponseClose'); + response.emit('close'); + delete global.yepsZipTestResponseClose; + } +}); diff --git a/lib/methodCheck.js b/lib/methodCheck.js index 72be071..8b960b6 100644 --- a/lib/methodCheck.js +++ b/lib/methodCheck.js @@ -1,8 +1,7 @@ -const debug = require('debug')('yeps:static:head'); - -module.exports = async method => { - - debug('Method: %s', method); - - return ['HEAD', 'GET'].includes(method) ? Promise.resolve() : Promise.reject(); -}; \ No newline at end of file +const debug = require('debug')('yeps:static:head'); + +module.exports = async (method) => { + debug('Method: %s', method); + + return ['HEAD', 'GET'].includes(method) ? Promise.resolve() : Promise.reject(); +}; diff --git a/package.json b/package.json index 6da4cb0..6c04806 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,16 @@ { "name": "yeps-static", - "version": "1.2.0", + "version": "1.3.0", "description": "YEPS static", "main": "index.js", "scripts": { - "lint": "./node_modules/.bin/npm-run-all --parallel lint:**", - "lint:js": "./node_modules/.bin/eslint index.js tests", - "test": "./node_modules/.bin/npm-run-all --parallel test:**", - "test:security": "./node_modules/.bin/nsp check", - "test:code": "node ./node_modules/mocha/bin/_mocha tests --recursive", - "test:coverage": "./node_modules/.bin/istanbul cover ./node_modules/mocha/bin/_mocha -- tests --recursive", - "report": "cat ./coverage/lcov.info | ./node_modules/.bin/coveralls", - "clear": "./node_modules/.bin/rimraf coverage", + "test": "npm-run-all test:**", + "test:lint": "eslint index.js lib tests", + "test:security": "nsp check", + "test:code": "mocha tests --recursive", + "test:coverage": "istanbul cover _mocha -- tests --recursive", + "report": "cat ./coverage/lcov.info | coveralls", + "clear": "rimraf coverage", "precommit": "npm run lint && npm test", "prepush": "npm run lint && npm test" }, @@ -47,31 +46,29 @@ "node": ">=7.6.0" }, "devDependencies": { - "chai": "^3.5.0", + "chai": "^4.1.2", "chai-http": "^3.0.0", - "coveralls": "^2.12.0", - "debug": "^2.6.3", - "eslint": "^3.18.0", - "eslint-config-eslint": "^3.0.0", - "husky": "^0.13.2", + "coveralls": "^3.0.0", + "eslint": "^4.10.0", + "eslint-config-airbnb-base": "^12.1.0", + "eslint-plugin-import": "^2.8.0", + "husky": "^0.14.3", "istanbul": "^1.1.0-alpha.1", - "mocha": "^3.2.0", + "mocha": "^4.0.1", "mocha-lcov-reporter": "^1.3.0", - "npm-run-all": "^4.0.2", - "nsp": "^2.6.3", - "rimraf": "^2.6.1", - "sinon": "^1.17.7" + "npm-run-all": "^4.1.1", + "nsp": "^3.0.0", + "rimraf": "^2.6.2", + "yeps": "^1.0.1", + "yeps-error": "^1.2.2", + "yeps-router": "^1.1.2", + "yeps-server": "^1.1.0", + "yeps-virtual-host": "^1.0.1" }, "dependencies": { - "coveralls": "^2.13.1", - "debug": "^2.6.6", - "mime-types": "^2.1.15", - "mocha": "^3.3.0", - "mz": "^2.6.0", - "resolve-path": "^1.3.3", - "yeps": "^1.0.0", - "yeps-error": "^1.2.0", - "yeps-method-override": "^1.0.1", - "yeps-virtual-host": "^1.0.0" + "debug": "^3.1.0", + "mime-types": "^2.1.17", + "mz": "^2.7.0", + "resolve-path": "^1.3.3" } } diff --git a/tests/errors.js b/tests/errors.js index 2084e89..575e979 100644 --- a/tests/errors.js +++ b/tests/errors.js @@ -1,162 +1,167 @@ -const App = require('yeps'); -const error = require('yeps-error'); -const chai = require('chai'); -const chaiHttp = require('chai-http'); -const http = require('http'); -const serve = require('..'); -const expect = chai.expect; - -chai.use(chaiHttp); -let app; - -describe('YEPS static errors', async () => { - - beforeEach(() => { - app = new App(); - app.then(error()); - }); - - it('should test file readStream error', async () => { - let isTestFinished = false; - - app.then(serve({ - root: __dirname, - gzip: false - })); - - global.yepsTestReadStream = true; - - await chai.request(http.createServer(app.resolve())) - .get('/files/index.html') - .send() - .catch(err => { - expect(err).to.have.status(500); - isTestFinished = true; - }); - - expect(isTestFinished).is.true; - }); - - it('should test file response error', async () => { - let isTestFinished = false; - - app.then(serve({ - root: __dirname, - gzip: false - })); - - global.yepsTestResponseError = true; - - await chai.request(http.createServer(app.resolve())) - .get('/files/index.html') - .send() - .catch(err => { - expect(err).to.have.status(500); - isTestFinished = true; - }); - - expect(isTestFinished).is.true; - }); - - it('should test file response close', async () => { - let isTestFinished = false; - - app.then(serve({ - root: __dirname, - gzip: false - })); - - global.yepsTestResponseClose = true; - - await chai.request(http.createServer(app.resolve())) - .get('/files/index.html') - .send() - .catch(err => { - expect(err).to.have.status(500); - isTestFinished = true; - }); - - expect(isTestFinished).is.true; - }); - - it('should test zip readStream error', async () => { - let isTestFinished = false; - - app.then(serve({ - root: __dirname - })); - - global.yepsZipTestReadStream = true; - - await chai.request(http.createServer(app.resolve())) - .get('/files/index.html') - .send() - .catch(err => { - expect(err).to.have.status(500); - isTestFinished = true; - }); - - expect(isTestFinished).is.true; - }); - - it('should test zip zipStream error', async () => { - let isTestFinished = false; - - app.then(serve({ - root: __dirname - })); - - global.yepsZipTestZipStream = true; - - await chai.request(http.createServer(app.resolve())) - .get('/files/index.html') - .send() - .catch(err => { - expect(err).to.have.status(500); - isTestFinished = true; - }); - - expect(isTestFinished).is.true; - }); - - it('should test zip response error', async () => { - let isTestFinished = false; - - app.then(serve({ - root: __dirname - })); - - global.yepsZipTestResponseError = true; - - await chai.request(http.createServer(app.resolve())) - .get('/files/index.html') - .send() - .catch(err => { - expect(err).to.have.status(500); - isTestFinished = true; - }); - - expect(isTestFinished).is.true; - }); - - it('should test zip response close', async () => { - let isTestFinished = false; - - app.then(serve({ - root: __dirname - })); - - global.yepsZipTestResponseClose = true; - - await chai.request(http.createServer(app.resolve())) - .get('/files/index.html') - .send() - .catch(err => { - expect(err).to.have.status(500); - isTestFinished = true; - }); - - expect(isTestFinished).is.true; - }); - -}); +const App = require('yeps'); +const error = require('yeps-error'); +const chai = require('chai'); +const chaiHttp = require('chai-http'); +const srv = require('yeps-server'); +const serve = require('..'); + +const { expect } = chai; + +chai.use(chaiHttp); +let app; +let server; + +describe('YEPS static errors', async () => { + beforeEach(() => { + app = new App(); + app.then(error()); + server = srv.createHttpServer(app); + }); + + afterEach(() => { + server.close(); + }); + + it('should test file readStream error', async () => { + let isTestFinished = false; + + app.then(serve({ + root: __dirname, + gzip: false, + })); + + global.yepsTestReadStream = true; + + await chai.request(server) + .get('/files/index.html') + .send() + .catch((err) => { + expect(err).to.have.status(500); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); + + it('should test file response error', async () => { + let isTestFinished = false; + + app.then(serve({ + root: __dirname, + gzip: false, + })); + + global.yepsTestResponseError = true; + + await chai.request(server) + .get('/files/index.html') + .send() + .catch((err) => { + expect(err).to.have.status(500); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); + + it('should test file response close', async () => { + let isTestFinished = false; + + app.then(serve({ + root: __dirname, + gzip: false, + })); + + global.yepsTestResponseClose = true; + + await chai.request(server) + .get('/files/index.html') + .send() + .catch((err) => { + expect(err).to.have.status(500); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); + + it('should test zip readStream error', async () => { + let isTestFinished = false; + + app.then(serve({ + root: __dirname, + })); + + global.yepsZipTestReadStream = true; + + await chai.request(server) + .get('/files/index.html') + .send() + .catch((err) => { + expect(err).to.have.status(500); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); + + it('should test zip zipStream error', async () => { + let isTestFinished = false; + + app.then(serve({ + root: __dirname, + })); + + global.yepsZipTestZipStream = true; + + await chai.request(server) + .get('/files/index.html') + .send() + .catch((err) => { + expect(err).to.have.status(500); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); + + it('should test zip response error', async () => { + let isTestFinished = false; + + app.then(serve({ + root: __dirname, + })); + + global.yepsZipTestResponseError = true; + + await chai.request(server) + .get('/files/index.html') + .send() + .catch((err) => { + expect(err).to.have.status(500); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); + + it('should test zip response close', async () => { + let isTestFinished = false; + + app.then(serve({ + root: __dirname, + })); + + global.yepsZipTestResponseClose = true; + + await chai.request(server) + .get('/files/index.html') + .send() + .catch((err) => { + expect(err).to.have.status(500); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); +}); diff --git a/tests/index.js b/tests/index.js index 216cefd..5484ddf 100644 --- a/tests/index.js +++ b/tests/index.js @@ -2,248 +2,336 @@ const App = require('yeps'); const error = require('yeps-error'); const chai = require('chai'); const chaiHttp = require('chai-http'); -const http = require('http'); +const srv = require('yeps-server'); +const Router = require('yeps-router'); +const VirtualHost = require('yeps-virtual-host'); const serve = require('..'); -const expect = chai.expect; + +const { expect } = chai; chai.use(chaiHttp); let app; +let server; describe('YEPS static', async () => { - - beforeEach(() => { - app = new App(); - app.then(error()); - }); - - it('should test etag', async () => { - let isTestFinished = false; - - app.then(serve()); - - await chai.request(http.createServer(app.resolve())) - .get('/files/index.html') - .set('etag', '/index.html') - .send() - .catch(err => { - expect(err).to.have.status(304); - isTestFinished = true; - }); - - expect(isTestFinished).is.true; - }); - - it('should test index file', async () => { - let isTestFinished = false; - - app.then(serve({ - root: __dirname - })); - - await chai.request(http.createServer(app.resolve())) - .get('/files/') - .send() - .then(res => { - expect(res).to.have.status(200); - isTestFinished = true; - }); - - expect(isTestFinished).is.true; + beforeEach(() => { + app = new App(); + app.then(error()); + server = srv.createHttpServer(app); + }); + + afterEach(() => { + server.close(); + }); + + it('should test etag', async () => { + let isTestFinished = false; + + app.then(serve()); + + await chai.request(server) + .get('/files/index.html') + .set('etag', '/index.html') + .send() + .catch((err) => { + expect(err).to.have.status(304); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); + + it('should test index file', async () => { + let isTestFinished = false; + + app.then(serve({ + root: __dirname, + })); + + await chai.request(server) + .get('/files/') + .send() + .then((res) => { + expect(res).to.have.status(200); + expect(res.text).to.include('
Index
'); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); + + it('should test without gzip', async () => { + let isTestFinished = false; + + app.then(serve({ + root: __dirname, + gzip: false, + })); + + await chai.request(server) + .get('/files/') + .send() + .then((res) => { + expect(res).to.have.status(200); + expect(res.headers['content-encoding']).to.be.undefined; + expect(res.text).to.include('
Index
'); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); + + it('should test 404', async () => { + let isTestFinished = false; + + app.then(serve({ + root: __dirname, + })); + + await chai.request(server) + .get('/index.html') + .send() + .catch((err) => { + expect(err).to.have.status(404); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); + + it('should test 500', async () => { + let isTestFinished = false; + + app.then(serve({ + root: __dirname, + })); + + await chai.request(server) + .get('/files/../../../../test.html') + .send() + .catch((err) => { + expect(err).to.have.status(500); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); + + it('should test etag: false', async () => { + let isTestFinished = false; + + app.then(serve({ + root: __dirname, + etag: false, + })); + + await chai.request(server) + .get('/files/') + .send() + .then((res) => { + expect(res).to.have.status(200); + expect(res.headers.etag).to.be.undefined; + expect(res.text).to.include('
Index
'); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); + + it('should test maxage', async () => { + let isTestFinished = false; + + app.then(serve({ + root: __dirname, + maxage: 9000, + })); + + await chai.request(server) + .get('/files/') + .send() + .then((res) => { + expect(res).to.have.status(200); + expect(res.headers['cache-control']).to.be.equal('max-age=9'); + expect(res.text).to.include('
Index
'); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); + + it('should test deflate', async () => { + let isTestFinished = false; + + app.then(serve({ + root: __dirname, + })); + + await chai.request(server) + .get('/files/') + .set('Accept-Encoding', 'gzip,deflate') + .send() + .then((res) => { + expect(res).to.have.status(200); + expect(res.headers['content-encoding']).to.be.equal('deflate'); + expect(res.text).to.include('
Index
'); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); + + it('should test gzip', async () => { + let isTestFinished = false; + + app.then(serve({ + root: __dirname, + })); + + await chai.request(server) + .get('/files/') + .set('Accept-Encoding', 'gzip') + .send() + .then((res) => { + expect(res).to.have.status(200); + expect(res.headers['content-encoding']).to.be.equal('gzip'); + expect(res.text).to.include('
Index
'); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); + + it('should test wrong method', async () => { + let isTestFinished = false; + + app.then(serve({ + root: __dirname, + })); + + await chai.request(server) + .delete('/files/index.html') + .send() + .catch((err) => { + expect(err).to.have.status(404); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); + + it('should test gzip', async () => { + let isTestFinished = false; + + app.then(async (ctx) => { + delete ctx.req.headers['accept-encoding']; }); - it('should test without gzip', async () => { - let isTestFinished = false; - - app.then(serve({ - root: __dirname, - gzip: false - })); - - await chai.request(http.createServer(app.resolve())) - .get('/files/') - .send() - .then(res => { - expect(res).to.have.status(200); - expect(res.headers['content-encoding']).to.be.undefined; - isTestFinished = true; - }); - - expect(isTestFinished).is.true; - }); - - it('should test 404', async () => { - let isTestFinished = false; - - app.then(serve({ - root: __dirname - })); - - await chai.request(http.createServer(app.resolve())) - .get('/index.html') - .send() - .catch(err => { - expect(err).to.have.status(404); - isTestFinished = true; - }); - - expect(isTestFinished).is.true; - }); - - it('should test 500', async () => { - let isTestFinished = false; - - app.then(serve({ - root: __dirname - })); - - await chai.request(http.createServer(app.resolve())) - .get('/files/../../../../test.html') - .send() - .catch(err => { - expect(err).to.have.status(500); - isTestFinished = true; - }); - - expect(isTestFinished).is.true; - }); - - it('should test etag: false', async () => { - let isTestFinished = false; - - app.then(serve({ - root: __dirname, - etag: false - })); - - await chai.request(http.createServer(app.resolve())) - .get('/files/') - .send() - .then(res => { - expect(res).to.have.status(200); - expect(res.headers.etag).to.be.undefined; - isTestFinished = true; - }); - - expect(isTestFinished).is.true; - }); - - it('should test maxage', async () => { - let isTestFinished = false; - - app.then(serve({ - root: __dirname, - maxage: 9000 - })); - - await chai.request(http.createServer(app.resolve())) - .get('/files/') - .send() - .then(res => { - expect(res).to.have.status(200); - expect(res.headers['cache-control']).to.be.equal('max-age=9'); - isTestFinished = true; - }); - - expect(isTestFinished).is.true; - }); - - it('should test deflate', async () => { - let isTestFinished = false; - - app.then(serve({ - root: __dirname - })); - - await chai.request(http.createServer(app.resolve())) - .get('/files/') - .set('Accept-Encoding', 'gzip,deflate') - .send() - .then(res => { - expect(res).to.have.status(200); - expect(res.headers['content-encoding']).to.be.equal('deflate'); - isTestFinished = true; - }); - - expect(isTestFinished).is.true; - }); - - it('should test gzip', async () => { - let isTestFinished = false; - - app.then(serve({ - root: __dirname - })); - - await chai.request(http.createServer(app.resolve())) - .get('/files/') - .set('Accept-Encoding', 'gzip') - .send() - .then(res => { - expect(res).to.have.status(200); - expect(res.headers['content-encoding']).to.be.equal('gzip'); - isTestFinished = true; - }); - - expect(isTestFinished).is.true; - }); - - it('should test wrong method', async () => { - let isTestFinished = false; - - app.then(serve({ - root: __dirname - })); - - await chai.request(http.createServer(app.resolve())) - .delete('/files/index.html') - .send() - .catch(err => { - expect(err).to.have.status(404); - isTestFinished = true; - }); - - expect(isTestFinished).is.true; - }); - - it('should test gzip', async () => { - let isTestFinished = false; - - app.then(async ctx => { - delete ctx.req.headers['accept-encoding']; - }); - - app.then(serve({ - root: __dirname - })); - - await chai.request(http.createServer(app.resolve())) - .get('/files/index.html') - .send() - .then(res => { - expect(res).to.have.status(200); - expect(res.headers['content-encoding']).to.be.equal('gzip'); - isTestFinished = true; - }); - - expect(isTestFinished).is.true; - }); - - it('should test directory', async () => { - let isTestFinished = false; - - app.then(serve({ - root: __dirname - })); - - await chai.request(http.createServer(app.resolve())) - .get('/files') - .send() - .then(res => { - expect(res).to.have.status(200); - isTestFinished = true; - }); - - expect(isTestFinished).is.true; + app.then(serve({ + root: __dirname, + })); + + await chai.request(server) + .get('/files/index.html') + .send() + .then((res) => { + expect(res).to.have.status(200); + expect(res.headers['content-encoding']).to.be.equal('gzip'); + expect(res.text).to.include('
Index
'); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); + + it('should test directory', async () => { + let isTestFinished = false; + + app.then(serve({ + root: __dirname, + })); + + await chai.request(server) + .get('/files') + .send() + .then((res) => { + expect(res).to.have.status(200); + expect(res.text).to.include('
Index
'); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); + + it('should test directory without gzip', async () => { + let isTestFinished = false; + + app.then(serve({ + root: __dirname, + gzip: false, + })); + + await chai.request(server) + .get('/files') + .send() + .then((res) => { + expect(res).to.have.status(200); + expect(res.text).to.include('
Index
'); + isTestFinished = true; + }); + + expect(isTestFinished).is.true; + }); + + it('should test virtual host with router from readme', async () => { + let isTestFinished1 = false; + let isTestFinished2 = false; + let isTestFinished3 = false; + + const vhost = new VirtualHost(); + const router = new Router(); + + router.get('/').then(async (ctx) => { + isTestFinished1 = true; + ctx.res.statusCode = 200; + ctx.res.setHeader('Content-Type', 'application/json'); + ctx.res.end(JSON.stringify({ status: 'OK' })); }); + vhost + .http('api.yeps.info') + .then(router.resolve()); + + vhost + .http('static.yeps.info') + .then(serve({ + root: __dirname, + })); + + app.then(vhost.resolve()); + + await chai.request(server) + .get('/') + .set('Host', 'api.yeps.info') + .send() + .then((res) => { + expect(res).to.have.status(200); + expect(res.body).to.haveOwnProperty('status'); + expect(res.body.status).to.be.equal('OK'); + isTestFinished2 = true; + }); + + await chai.request(server) + .get('/files/index.html') + .set('Host', 'static.yeps.info') + .send() + .then((res) => { + expect(res).to.have.status(200); + expect(res.text).to.include('
Index
'); + isTestFinished3 = true; + }); + + expect(isTestFinished1).is.true; + expect(isTestFinished2).is.true; + expect(isTestFinished3).is.true; + }); });