#415 Missing body for POST request in middleware (#576)

* Missing postbody in middleware

Added body parser to server defaults.

* Test name change

Capitol letter is now lower case

* Missing postbody in middleware

Added body parser to server defaults.

* Test name change

Capitol letter is now lower case

* Added postbody as option to defaults

* Missing postbody in middleware

Added body parser to server defaults.

* Test name change

Capitol letter is now lower case

* Missing postbody in middleware

Added body parser to server defaults.

* Added postbody as option to defaults

* Setting bodyParser as enabled by default for cli
This commit is contained in:
JHotterbeekx
2017-07-14 02:41:55 +02:00
committed by typicode
parent b9f63b9d77
commit 6ca65ef982
4 changed files with 321 additions and 298 deletions

View File

@ -56,7 +56,8 @@ function createApp(source, object, routes, middlewares, argv) {
logger: !argv.quiet, logger: !argv.quiet,
readOnly: argv.readOnly, readOnly: argv.readOnly,
noCors: argv.noCors, noCors: argv.noCors,
noGzip: argv.noGzip noGzip: argv.noGzip,
bodyParser: true
} }
if (argv.static) { if (argv.static) {

View File

@ -6,6 +6,7 @@ const cors = require('cors')
const compression = require('compression') const compression = require('compression')
const errorhandler = require('errorhandler') const errorhandler = require('errorhandler')
const objectAssign = require('object-assign') const objectAssign = require('object-assign')
const bodyParser = require('./body-parser')
module.exports = function(opts) { module.exports = function(opts) {
const userDir = path.join(process.cwd(), 'public') const userDir = path.join(process.cwd(), 'public')
@ -64,5 +65,10 @@ module.exports = function(opts) {
}) })
} }
// Add middlewares
if (opts.bodyParser) {
arr.push(bodyParser)
}
return arr return arr
} }

View File

@ -0,0 +1,4 @@
module.exports = function(req, res, next) {
res.header('name', req.body.name)
next()
}

View File

@ -1,297 +1,309 @@
const fs = require('fs') const fs = require('fs')
const path = require('path') const path = require('path')
const cp = require('child_process') const cp = require('child_process')
const assert = require('assert') const assert = require('assert')
const supertest = require('supertest') const supertest = require('supertest')
const osTmpdir = require('os-tmpdir') const osTmpdir = require('os-tmpdir')
const tempWrite = require('temp-write') const tempWrite = require('temp-write')
const mkdirp = require('mkdirp') const mkdirp = require('mkdirp')
const rimraf = require('rimraf') const rimraf = require('rimraf')
const express = require('express') const express = require('express')
const serverReady = require('server-ready') const serverReady = require('server-ready')
let PORT = 3100 let PORT = 3100
const middlewareFiles = { const middlewareFiles = {
en: './fixtures/middlewares/en.js', en: './fixtures/middlewares/en.js',
jp: './fixtures/middlewares/jp.js' jp: './fixtures/middlewares/jp.js',
} postbody: './fixtures/middlewares/postbody.js'
}
const bin = path.join(__dirname, '../../lib/cli/bin')
const bin = path.join(__dirname, '../../lib/cli/bin')
function cli(args) {
return cp.spawn('node', ['--', bin, '-p', PORT].concat(args), { function cli(args) {
cwd: __dirname, return cp.spawn('node', ['--', bin, '-p', PORT].concat(args), {
stdio: ['pipe', process.stdout, process.stderr] cwd: __dirname,
}) stdio: ['pipe', process.stdout, process.stderr]
} })
}
describe('cli', () => {
let child describe('cli', () => {
let request let child
let dbFile let request
let routesFile let dbFile
let routesFile
beforeEach(() => {
dbFile = tempWrite.sync( beforeEach(() => {
JSON.stringify({ dbFile = tempWrite.sync(
posts: [{ id: 1 }, { _id: 2 }], JSON.stringify({
comments: [{ id: 1, post_id: 1 }] posts: [{ id: 1 }, { _id: 2 }],
}), comments: [{ id: 1, post_id: 1 }]
'db.json' }),
) 'db.json'
)
routesFile = tempWrite.sync(
JSON.stringify({ '/blog/*': '/$1' }), routesFile = tempWrite.sync(
'routes.json' JSON.stringify({ '/blog/*': '/$1' }),
) 'routes.json'
)
++PORT
request = supertest(`http://localhost:${PORT}`) ++PORT
}) request = supertest(`http://localhost:${PORT}`)
})
afterEach(() => {
child.kill('SIGKILL') afterEach(() => {
}) child.kill('SIGKILL')
})
describe('db.json', () => {
beforeEach(done => { describe('db.json', () => {
child = cli([dbFile]) beforeEach(done => {
serverReady(PORT, done) child = cli([dbFile])
}) serverReady(PORT, done)
})
it('should support JSON file', done => {
request.get('/posts').expect(200, done) it('should support JSON file', done => {
}) request.get('/posts').expect(200, done)
})
it('should send CORS headers', done => {
const origin = 'http://example.com' it('should send CORS headers', done => {
const origin = 'http://example.com'
request
.get('/posts') request
.set('Origin', origin) .get('/posts')
.expect('access-control-allow-origin', origin) .set('Origin', origin)
.expect(200, done) .expect('access-control-allow-origin', origin)
}) .expect(200, done)
})
it('should update JSON file', done => {
request.post('/posts').send({ title: 'hello' }).end(() => { it('should update JSON file', done => {
setTimeout(() => { request.post('/posts').send({ title: 'hello' }).end(() => {
const str = fs.readFileSync(dbFile, 'utf8') setTimeout(() => {
assert(str.indexOf('hello') !== -1) const str = fs.readFileSync(dbFile, 'utf8')
done() assert(str.indexOf('hello') !== -1)
}, 1000) done()
}) }, 1000)
}) })
}) })
})
describe('seed.js', () => {
beforeEach(done => { describe('seed.js', () => {
child = cli(['fixtures/seed.js']) beforeEach(done => {
serverReady(PORT, done) child = cli(['fixtures/seed.js'])
}) serverReady(PORT, done)
})
it('should support JS file', done => {
request.get('/posts').expect(200, done) it('should support JS file', done => {
}) request.get('/posts').expect(200, done)
}) })
})
describe('http://localhost:8080/db', () => {
beforeEach(done => { describe('http://localhost:8080/db', () => {
const fakeServer = express() beforeEach(done => {
fakeServer.get('/db', (req, res) => { const fakeServer = express()
res.jsonp({ posts: [] }) fakeServer.get('/db', (req, res) => {
}) res.jsonp({ posts: [] })
fakeServer.listen(8080, () => { })
child = cli(['http://localhost:8080/db']) fakeServer.listen(8080, () => {
serverReady(PORT, done) child = cli(['http://localhost:8080/db'])
}) serverReady(PORT, done)
}) })
})
it('should support URL file', done => {
request.get('/posts').expect(200, done) it('should support URL file', done => {
}) request.get('/posts').expect(200, done)
}) })
})
describe('db.json -r routes.json -m middleware.js -i _id --foreignKeySuffix _id --read-only', () => {
beforeEach(done => { describe('db.json -r routes.json -m middleware.js -i _id --foreignKeySuffix _id --read-only', () => {
child = cli([ beforeEach(done => {
dbFile, child = cli([
'-r', dbFile,
routesFile, '-r',
'-m', routesFile,
middlewareFiles.en, '-m',
'-i', middlewareFiles.en,
'_id', '-i',
'--read-only', '_id',
'--foreignKeySuffix', '--read-only',
'_id' '--foreignKeySuffix',
]) '_id'
serverReady(PORT, done) ])
}) serverReady(PORT, done)
})
it('should use routes.json and _id as the identifier', done => {
request.get('/blog/posts/2').expect(200, done) it('should use routes.json and _id as the identifier', done => {
}) request.get('/blog/posts/2').expect(200, done)
})
it('should use _id as foreignKeySuffix', async () => {
const response = await request.get('/posts/1/comments') it('should use _id as foreignKeySuffix', async () => {
assert.equal(response.body.length, 1) const response = await request.get('/posts/1/comments')
}) assert.equal(response.body.length, 1)
})
it('should apply middlewares', done => {
request.get('/blog/posts/2').expect('X-Hello', 'World', done) it('should apply middlewares', done => {
}) request.get('/blog/posts/2').expect('X-Hello', 'World', done)
})
it('should allow only GET requests', done => {
request.post('/blog/posts').expect(403, done) it('should allow only GET requests', done => {
}) request.post('/blog/posts').expect(403, done)
}) })
})
describe('db.json -m first-middleware.js second-middleware.js', () => {
beforeEach(done => { describe('db.json -m first-middleware.js second-middleware.js', () => {
child = cli([dbFile, '-m', middlewareFiles.en, middlewareFiles.jp]) beforeEach(done => {
serverReady(PORT, done) child = cli([dbFile, '-m', middlewareFiles.en, middlewareFiles.jp])
}) serverReady(PORT, done)
})
it('should apply all middlewares', done => {
request it('should apply all middlewares', done => {
.get('/posts') request
.expect('X-Hello', 'World') .get('/posts')
.expect('X-Konnichiwa', 'Sekai', done) .expect('X-Hello', 'World')
}) .expect('X-Konnichiwa', 'Sekai', done)
}) })
})
describe('db.json -d 1000', () => {
beforeEach(done => { describe('db.json -m postbody-middleware.js', () => {
child = cli([dbFile, '-d', 1000]) beforeEach(done => {
serverReady(PORT, done) child = cli([dbFile, '-m', middlewareFiles.postbody])
}) serverReady(PORT, done)
})
it('should delay response', done => {
const start = new Date() it('should have post body in middleware', done => {
request.get('/posts').expect(200, function(err) { request.post('/posts').send({ name: 'test' }).expect('name', 'test', done)
const end = new Date() })
done(end - start > 1000 ? err : new Error("Request wasn't delayed")) })
})
}) describe('db.json -d 1000', () => {
}) beforeEach(done => {
child = cli([dbFile, '-d', 1000])
describe('db.json -s fixtures/public -S /some/path/snapshots', () => { serverReady(PORT, done)
const snapshotsDir = path.join(osTmpdir(), 'snapshots') })
const publicDir = 'fixtures/public'
it('should delay response', done => {
beforeEach(done => { const start = new Date()
rimraf.sync(snapshotsDir) request.get('/posts').expect(200, function(err) {
mkdirp.sync(snapshotsDir) const end = new Date()
done(end - start > 1000 ? err : new Error("Request wasn't delayed"))
child = cli([dbFile, '-s', publicDir, '-S', snapshotsDir]) })
serverReady(PORT, () => { })
child.stdin.write('s\n') })
setTimeout(done, 100)
}) describe('db.json -s fixtures/public -S /some/path/snapshots', () => {
}) const snapshotsDir = path.join(osTmpdir(), 'snapshots')
const publicDir = 'fixtures/public'
it('should serve fixtures/public', done => {
request.get('/').expect(/Hello/, done) beforeEach(done => {
}) rimraf.sync(snapshotsDir)
mkdirp.sync(snapshotsDir)
it('should save a snapshot in snapshots dir', () => {
assert.equal(fs.readdirSync(snapshotsDir).length, 1) child = cli([dbFile, '-s', publicDir, '-S', snapshotsDir])
}) serverReady(PORT, () => {
}) child.stdin.write('s\n')
setTimeout(done, 100)
describe('fixtures/seed.json --no-cors=true', () => { })
beforeEach(done => { })
child = cli(['fixtures/seed.js', '--no-cors=true'])
serverReady(PORT, done) it('should serve fixtures/public', done => {
}) request.get('/').expect(/Hello/, done)
})
it('should not send Access-Control-Allow-Origin headers', done => {
const origin = 'http://example.com' it('should save a snapshot in snapshots dir', () => {
assert.equal(fs.readdirSync(snapshotsDir).length, 1)
request })
.get('/posts') })
.set('Origin', origin)
.expect(200) describe('fixtures/seed.json --no-cors=true', () => {
.end((err, res) => { beforeEach(done => {
if (err) { child = cli(['fixtures/seed.js', '--no-cors=true'])
done(err) serverReady(PORT, done)
} })
if ('access-control-allow-origin' in res.headers) {
done(new Error('CORS headers were not excluded from response')) it('should not send Access-Control-Allow-Origin headers', done => {
} else { const origin = 'http://example.com'
done()
} request
}) .get('/posts')
}) .set('Origin', origin)
}) .expect(200)
.end((err, res) => {
describe('fixtures/seed.json --no-gzip=true', () => { if (err) {
beforeEach(done => { done(err)
child = cli(['fixtures/seed.js', '--no-gzip=true']) }
serverReady(PORT, done) if ('access-control-allow-origin' in res.headers) {
}) done(new Error('CORS headers were not excluded from response'))
} else {
it('should not set Content-Encoding to gzip', done => { done()
request.get('/posts').expect(200).end(function(err, res) { }
if (err) { })
done(err) })
} else if ('content-encoding' in res.headers) { })
done(new Error('Content-Encoding is set to gzip'))
} else { describe('fixtures/seed.json --no-gzip=true', () => {
done() beforeEach(done => {
} child = cli(['fixtures/seed.js', '--no-gzip=true'])
}) serverReady(PORT, done)
}) })
})
it('should not set Content-Encoding to gzip', done => {
describe('--watch db.json -r routes.json', () => { request.get('/posts').expect(200).end(function(err, res) {
beforeEach(done => { if (err) {
child = cli([dbFile, '-r', routesFile, '--watch']) done(err)
serverReady(PORT, done) } else if ('content-encoding' in res.headers) {
}) done(new Error('Content-Encoding is set to gzip'))
} else {
it('should watch db file', done => { done()
fs.writeFileSync(dbFile, JSON.stringify({ foo: [] })) }
setTimeout(() => { })
request.get('/foo').expect(200, done) })
}, 1000) })
})
describe('--watch db.json -r routes.json', () => {
it('should watch routes file', done => { beforeEach(done => {
fs.writeFileSync(routesFile, JSON.stringify({ '/api/*': '/$1' })) child = cli([dbFile, '-r', routesFile, '--watch'])
setTimeout(() => { serverReady(PORT, done)
request.get('/api/posts').expect(200, done) })
}, 1000)
}) it('should watch db file', done => {
}) fs.writeFileSync(dbFile, JSON.stringify({ foo: [] }))
setTimeout(() => {
describe('non existent db.json', () => { request.get('/foo').expect(200, done)
beforeEach(done => { }, 1000)
fs.unlinkSync(dbFile) })
child = cli([dbFile])
serverReady(PORT, done) it('should watch routes file', done => {
}) fs.writeFileSync(routesFile, JSON.stringify({ '/api/*': '/$1' }))
setTimeout(() => {
it("should create JSON file if it doesn't exist", done => { request.get('/api/posts').expect(200, done)
request.get('/posts').expect(200, done) }, 1000)
}) })
}) })
describe('db.json with error', () => { describe('non existent db.json', () => {
beforeEach(() => { beforeEach(done => {
dbFile = tempWrite.sync(JSON.stringify({ 'a/b': [] }), 'db-error.json') fs.unlinkSync(dbFile)
}) child = cli([dbFile])
serverReady(PORT, done)
it('should exit with an error', done => { })
child = cli([dbFile])
child.on('exit', code => { it("should create JSON file if it doesn't exist", done => {
if (code === 1) { request.get('/posts').expect(200, done)
return done() })
} })
return done(new Error('should exit with error code'))
}) describe('db.json with error', () => {
}) beforeEach(() => {
}) dbFile = tempWrite.sync(JSON.stringify({ 'a/b': [] }), 'db-error.json')
}) })
it('should exit with an error', done => {
child = cli([dbFile])
child.on('exit', code => {
if (code === 1) {
return done()
}
return done(new Error('should exit with error code'))
})
})
})
})