From f39762b68bda383a4cf2cb1de2ba04c17e9d322d Mon Sep 17 00:00:00 2001 From: loicsaintroch Date: Tue, 20 Oct 2015 12:19:49 +0200 Subject: [PATCH 1/3] Update dependencies --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index b1ada39c77..900e116315 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "koa-cors": "^0.0.16", "koa-favicon": "^1.2.0", "koa-gzip": "^0.1.0", - "koa-i18n": "^1.1.0", + "koa-i18n": "^1.1.2", "koa-ip": "^0.1.0", "koa-load-middlewares": "^1.0.0", "koa-locale": "^1.0.0", @@ -74,16 +74,16 @@ "strapi-generate-users": "^1.1.0", "unzip2": "^0.2.5", "waterline": "^0.10.26", - "winston": "^1.1.0" + "winston": "^1.1.1" }, "devDependencies": { "babel": "^5.8.23", "babel-eslint": "^4.1.3", - "eslint": "^1.6.0", + "eslint": "^1.7.2", "eslint-config-standard": "^4.4.0", "eslint-plugin-standard": "^1.3.1", "expect.js": "^0.3.1", - "istanbul": "^0.3.22", + "istanbul": "^0.4.0", "jade": "^1.11.0", "make-lint": "^1.0.1", "methods": "^1.1.1", From 46b7c1e4fd7b156de89d0a1e661cbe9fd8708467 Mon Sep 17 00:00:00 2001 From: loicsaintroch Date: Tue, 20 Oct 2015 14:27:15 +0200 Subject: [PATCH 2/3] Add tests for the send middleware --- package.json | 2 + test/middlewares/proxy/index.js | 1 - test/middlewares/send/fixtures/.hidden | 1 + .../send/fixtures/.private/id_rsa.txt | 1 + test/middlewares/send/fixtures/gzip.json | 1 + test/middlewares/send/fixtures/hello.txt | 1 + test/middlewares/send/fixtures/index.txt | 1 + test/middlewares/send/fixtures/user.json | 1 + .../send/fixtures/world/index.html | 1 + test/middlewares/send/index.js | 513 ++++++++++++++++++ 10 files changed, 522 insertions(+), 1 deletion(-) create mode 100755 test/middlewares/send/fixtures/.hidden create mode 100755 test/middlewares/send/fixtures/.private/id_rsa.txt create mode 100755 test/middlewares/send/fixtures/gzip.json create mode 100755 test/middlewares/send/fixtures/hello.txt create mode 100755 test/middlewares/send/fixtures/index.txt create mode 100755 test/middlewares/send/fixtures/user.json create mode 100755 test/middlewares/send/fixtures/world/index.html create mode 100755 test/middlewares/send/index.js diff --git a/package.json b/package.json index 900e116315..5d013d40f4 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,8 @@ "babel-eslint": "^4.1.3", "eslint": "^1.7.2", "eslint-config-standard": "^4.4.0", + "eslint-config-xo": "^0.6.0", + "eslint-plugin-babel": "^2.1.1", "eslint-plugin-standard": "^1.3.1", "expect.js": "^0.3.1", "istanbul": "^0.4.0", diff --git a/test/middlewares/proxy/index.js b/test/middlewares/proxy/index.js index 1346162fac..8f3b1d8f83 100755 --- a/test/middlewares/proxy/index.js +++ b/test/middlewares/proxy/index.js @@ -1,7 +1,6 @@ 'use strict'; const path = require('path'); -const http = require('http'); const request = require('supertest'); diff --git a/test/middlewares/send/fixtures/.hidden b/test/middlewares/send/fixtures/.hidden new file mode 100755 index 0000000000..7addfc4e54 --- /dev/null +++ b/test/middlewares/send/fixtures/.hidden @@ -0,0 +1 @@ +You should never get here \ No newline at end of file diff --git a/test/middlewares/send/fixtures/.private/id_rsa.txt b/test/middlewares/send/fixtures/.private/id_rsa.txt new file mode 100755 index 0000000000..7addfc4e54 --- /dev/null +++ b/test/middlewares/send/fixtures/.private/id_rsa.txt @@ -0,0 +1 @@ +You should never get here \ No newline at end of file diff --git a/test/middlewares/send/fixtures/gzip.json b/test/middlewares/send/fixtures/gzip.json new file mode 100755 index 0000000000..24f0a0b34f --- /dev/null +++ b/test/middlewares/send/fixtures/gzip.json @@ -0,0 +1 @@ +{ "name": "tobi" } \ No newline at end of file diff --git a/test/middlewares/send/fixtures/hello.txt b/test/middlewares/send/fixtures/hello.txt new file mode 100755 index 0000000000..04fea06420 --- /dev/null +++ b/test/middlewares/send/fixtures/hello.txt @@ -0,0 +1 @@ +world \ No newline at end of file diff --git a/test/middlewares/send/fixtures/index.txt b/test/middlewares/send/fixtures/index.txt new file mode 100755 index 0000000000..2fa59a746e --- /dev/null +++ b/test/middlewares/send/fixtures/index.txt @@ -0,0 +1 @@ +text index \ No newline at end of file diff --git a/test/middlewares/send/fixtures/user.json b/test/middlewares/send/fixtures/user.json new file mode 100755 index 0000000000..24f0a0b34f --- /dev/null +++ b/test/middlewares/send/fixtures/user.json @@ -0,0 +1 @@ +{ "name": "tobi" } \ No newline at end of file diff --git a/test/middlewares/send/fixtures/world/index.html b/test/middlewares/send/fixtures/world/index.html new file mode 100755 index 0000000000..3e575fa8d8 --- /dev/null +++ b/test/middlewares/send/fixtures/world/index.html @@ -0,0 +1 @@ +html index \ No newline at end of file diff --git a/test/middlewares/send/index.js b/test/middlewares/send/index.js new file mode 100755 index 0000000000..6abbc533b1 --- /dev/null +++ b/test/middlewares/send/index.js @@ -0,0 +1,513 @@ +'use strict'; + +const path = require('path'); + +const request = require('supertest'); +const assert = require('assert'); + +const strapi = require('../../..'); +const Koa = strapi.server; + +describe('send', function () { + it('should set the Content-Type', function (done) { + const app = new Koa(); + + app.use(function * () { + yield strapi.middlewares.send(this, 'test/middlewares/send/fixtures/user.json'); + }); + + request(app.listen()) + .get('/') + .expect('Content-Type', /application\/json/) + .end(done); + }); + + it('should set the Content-Length', function (done) { + const app = new Koa(); + + app.use(function * () { + yield strapi.middlewares.send(this, 'test/middlewares/send/fixtures/user.json'); + }); + + request(app.listen()) + .get('/') + .expect('Content-Length', '18') + .end(done); + }); + + it('should cleanup on socket error', function (done) { + const app = new Koa(); + let stream; + + app.use(function * () { + yield strapi.middlewares.send(this, 'test/middlewares/send/fixtures/user.json'); + stream = this.body; + this.socket.emit('error', new Error('boom')); + }); + + request(app.listen()) + .get('/') + .expect(500, function (err) { + err.should.be.ok; + stream.destroyed.should.be.ok; + done(); + }); + }); + + describe('with no .root', function () { + describe('when the path is absolute', function () { + it('should 404', function (done) { + const app = new Koa(); + + app.use(function * () { + yield strapi.middlewares.send(this, path.resolve(__dirname, 'fixtures', 'hello.txt')); + }); + + request(app.listen()) + .get('/') + .expect(404, done); + }); + }); + + describe('when the path is relative', function () { + it('should 200', function (done) { + const app = new Koa(); + + app.use(function * () { + yield strapi.middlewares.send(this, '/test/middlewares/send/fixtures/hello.txt'); + }); + + request(app.listen()) + .get('/') + .expect(200) + .expect('world', done); + }); + }); + + describe('when the path contains ..', function () { + it('should 403', function (done) { + const app = new Koa(); + + app.use(function * () { + yield strapi.middlewares.send(this, '/../send/fixtures/hello.txt'); + }); + + request(app.listen()) + .get('/') + .expect(403, done); + }); + }); + }); + + describe('with .root', function () { + describe('when the path is absolute', function () { + it('should 404', function (done) { + const app = new Koa(); + + app.use(function * () { + const opts = { + root: 'test/fixtures' + }; + + yield strapi.middlewares.send(this, path.resolve(__dirname, 'fixtures', 'hello.txt'), opts); + }); + + request(app.listen()) + .get('/') + .expect(404, done); + }); + }); + + describe('when the path is relative and exists', function () { + it('should serve the file', function (done) { + const app = new Koa(); + + app.use(function * () { + const opts = { + root: 'test/middlewares/send/fixtures' + }; + + yield strapi.middlewares.send(this, 'hello.txt', opts); + }); + + request(app.listen()) + .get('/') + .expect(200) + .expect('world', done); + }); + }); + + describe('when the path is relative and does not exist', function () { + it('should 404', function (done) { + const app = new Koa(); + + app.use(function * () { + const opts = { + root: 'test/fixtures' + }; + + yield strapi.middlewares.send(this, 'something', opts); + }); + + request(app.listen()) + .get('/') + .expect(404, done); + }); + }); + + describe('when the path resolves above the root', function () { + it('should 403', function (done) { + const app = new Koa(); + + app.use(function * () { + const opts = { + root: 'test/fixtures' + }; + + yield strapi.middlewares.send(this, '../../../../package.json', opts); + }); + + request(app.listen()) + .get('/') + .expect(403, done); + }); + }); + + describe('when the path resolves within root', function () { + it('should 403', function (done) { + const app = new Koa(); + + app.use(function * () { + const opts = { + root: 'test/fixtures' + }; + + yield strapi.middlewares.send(this, '../../../../test/middlewares/send/fixtures/world/index.html', opts); + }); + + request(app.listen()) + .get('/') + .expect(403, done); + }); + }); + }); + + describe('with .index', function () { + describe('when the index file is present', function () { + it('should serve it', function (done) { + const app = new Koa(); + + app.use(function * () { + const opts = { + root: 'test/middlewares/send/', + index: 'index.html' + }; + + yield strapi.middlewares.send(this, 'fixtures/world/', opts); + }); + + request(app.listen()) + .get('/') + .expect(200) + .expect('html index', done); + }); + + it('should serve it', function (done) { + const app = new Koa(); + + app.use(function * () { + const opts = { + root: 'test/middlewares/send/fixtures/world', + index: 'index.html' + }; + + yield strapi.middlewares.send(this, this.path, opts); + }); + + request(app.listen()) + .get('/') + .expect(200) + .expect('html index', done); + }); + }); + }); + + describe('when path is not a file', function () { + it('should 404', function (done) { + const app = new Koa(); + + app.use(function * () { + yield strapi.middlewares.send(this, '/test/middlewares/send/'); + }); + + request(app.listen()) + .get('/') + .expect(404, done); + }); + + it('should return undefined', function (done) { + const app = new Koa(); + + app.use(function * () { + const sent = yield strapi.middlewares.send(this, '/test/middlewares/send/'); + assert.equal(sent, undefined); + }); + + request(app.listen()) + .get('/') + .expect(404, done); + }); + }); + + describe('when path is a directory', function () { + it('should 404', function (done) { + const app = new Koa(); + + app.use(function * () { + yield strapi.middlewares.send(this, '/test/middlewares/send/fixtures'); + }); + + request(app.listen()) + .get('/') + .expect(404, done); + }); + }); + + describe('when path does not finish with slash and format is disabled', function () { + it('should 404', function (done) { + const app = new Koa(); + + app.use(function * () { + const opts = { + root: 'test', + index: 'index.html' + }; + + yield strapi.middlewares.send(this, 'middlewares/send/fixtures/world', opts); + }); + + request(app.listen()) + .get('/world') + .expect(404, done); + }); + + it('should 404', function (done) { + const app = new Koa(); + + app.use(function * () { + const opts = { + root: 'test', + index: 'index.html', + format: false + }; + + yield strapi.middlewares.send(this, 'middlewares/send/fixtures/world', opts); + }); + + request(app.listen()) + .get('/world') + .expect(404, done); + }); + }); + + describe('when path does not finish with slash and format is enabled', function () { + it('should 200', function (done) { + const app = new Koa(); + + app.use(function * () { + const opts = { + root: 'test', + index: 'index.html', + format: true + }; + + yield strapi.middlewares.send(this, 'middlewares/send/fixtures/world', opts); + }); + + request(app.listen()) + .get('/') + .expect(200, done); + }); + }); + + describe('when path is malformed', function () { + it('should 400', function (done) { + const app = new Koa(); + + app.use(function * () { + yield strapi.middlewares.send(this, '/%'); + }); + + request(app.listen()) + .get('/') + .expect(400, done); + }); + }); + + describe('when path is a file', function () { + + it('should return the path', function (done) { + const app = new Koa(); + + app.use(function * () { + const p = '/test/middlewares/send/fixtures/user.json'; + const sent = yield strapi.middlewares.send(this, p); + assert.equal(sent, path.resolve(__dirname, 'fixtures', 'user.json')); + }); + + request(app.listen()) + .get('/') + .expect(200, done); + }); + + describe('or .gz version when requested and if possible', function () { + it('should return path', function (done) { + const app = new Koa(); + + app.use(function * () { + yield strapi.middlewares.send(this, 'test/middlewares/send/fixtures/gzip.json'); + }); + + request(app.listen()) + .get('/') + .set('Accept-Encoding', 'deflate, identity') + .expect('Content-Length', 18) + .expect('{ "name": "tobi" }') + .expect(200, done); + }); + + it('should return .gz path (gzip option defaults to true)', function (done) { + const app = new Koa(); + + app.use(function * () { + yield strapi.middlewares.send(this, 'test/middlewares/send/fixtures/gzip.json'); + }); + + request(app.listen()) + .get('/') + .set('Accept-Encoding', 'gzip, deflate, identity') + .expect('Content-Length', 48) + .expect('{ "name": "tobi" }') + .expect(200, done); + }); + + it('should return .gz path when gzip option is turned on', function (done) { + const app = new Koa(); + + app.use(function * () { + yield strapi.middlewares.send(this, 'test/middlewares/send/fixtures/gzip.json', { + gzip: true + }); + }); + + request(app.listen()) + .get('/') + .set('Accept-Encoding', 'gzip, deflate, identity') + .expect('Content-Length', 48) + .expect('{ "name": "tobi" }') + .expect(200, done); + }); + + it('should not return .gz path when gzip option is false', function (done) { + const app = new Koa(); + + app.use(function * () { + yield strapi.middlewares.send(this, 'test/middlewares/send/fixtures/gzip.json', { + gzip: false + }); + }); + + request(app.listen()) + .get('/') + .set('Accept-Encoding', 'gzip, deflate, identity') + .expect('Content-Length', 18) + .expect('{ "name": "tobi" }') + .expect(200, done); + }); + }); + + describe('and max age is specified', function () { + it('should set max-age in seconds', function (done) { + const app = new Koa(); + + app.use(function * () { + const p = '/test/middlewares/send/fixtures/user.json'; + const sent = yield strapi.middlewares.send(this, p, { + maxage: 5000 + }); + + assert.equal(sent, path.resolve(__dirname, 'fixtures', 'user.json')); + }); + + request(app.listen()) + .get('/') + .expect('Cache-Control', 'max-age=5') + .expect(200, done); + }); + + it('should truncate fractional values for max-age', function (done) { + const app = new Koa(); + + app.use(function * () { + const p = '/test/middlewares/send/fixtures/user.json'; + const sent = yield strapi.middlewares.send(this, p, { + maxage: 1234 + }); + + assert.equal(sent, path.resolve(__dirname, 'fixtures', 'user.json')); + }); + + request(app.listen()) + .get('/') + .expect('Cache-Control', 'max-age=1') + .expect(200, done); + }); + }); + }); + + describe('.hidden option', function () { + describe('when trying to get a hidden file', function () { + it('should 404', function (done) { + const app = new Koa(); + + app.use(function * () { + yield strapi.middlewares.send(this, path.resolve(__dirname, 'fixtures', '.hidden')); + }); + + request(app.listen()) + .get('/') + .expect(404, done); + }); + }); + + describe('when trying to get a file from a hidden directory', function () { + it('should 404', function (done) { + const app = new Koa(); + + app.use(function * () { + yield strapi.middlewares.send(this, path.resolve(__dirname, 'fixtures', '.private', 'id_rsa.txt')); + }); + + request(app.listen()) + .get('/') + .expect(404, done); + }); + }); + + describe('when trying to get a hidden file and .hidden check is turned off', function () { + it('should 200', function (done) { + const app = new Koa(); + + app.use(function * () { + yield strapi.middlewares.send(this, 'test/middlewares/send/fixtures/.hidden', { + hidden: true + }); + }); + + request(app.listen()) + .get('/') + .expect(200, done); + }); + }); + }); +}); From 2f369eba38f1a6e36d61eead38d681df2123e0a6 Mon Sep 17 00:00:00 2001 From: loicsaintroch Date: Tue, 20 Oct 2015 14:30:30 +0200 Subject: [PATCH 3/3] Uncomment views test for default engine --- test/middlewares/views/index.js | 38 ++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/test/middlewares/views/index.js b/test/middlewares/views/index.js index 88df9e5a9f..094c0f6c9d 100755 --- a/test/middlewares/views/index.js +++ b/test/middlewares/views/index.js @@ -23,25 +23,25 @@ describe('views', function () { .expect(404, done); }); - // it('default to html', function (done) { - // const app = new Koa(); - // const router = strapi.middlewares.router(); - // - // app.use(strapi.middlewares.views(path.resolve(__dirname, 'fixtures'))); - // - // router.get('/', function * () { - // yield this.render('basic'); - // }); - // - // app.use(router.routes()); - // app.use(router.allowedMethods()); - // - // request(app.listen()) - // .get('/') - // .expect('Content-Type', /html/) - // .expect(/basic:html/) - // .expect(200, done); - // }); + it('default to html', function (done) { + const app = new Koa(); + const router = strapi.middlewares.router(); + + app.use(strapi.middlewares.views(path.resolve(__dirname, 'fixtures'))); + + router.get('/', function * () { + yield this.render('basic'); + }); + + app.use(router.routes()); + app.use(router.allowedMethods()); + + request(app.listen()) + .get('/') + .expect('Content-Type', /html/) + .expect(/basic:html/) + .expect(200, done); + }); it('default to ext if a default engine is set', function (done) { const app = new Koa();