Commit c4e1b4cd authored by Bryan Tong's avatar Bryan Tong
Browse files

Merge branch 'jsonParse' into 'master'

More gracefully handle incoming JSON parse failures.

Closes #110

See merge request kado/kado!310
parents 70a7da47 42381867
Pipeline #8450 passed with stage
in 2 minutes and 23 seconds
......@@ -4,9 +4,10 @@
*Pending*
* Log now writes to console synchronously when toConsole is on.
* Improved log dump to work with all variable types.
* Better log dumping on errors.
* Better log dumping on errors. Fixes #108
* Added `log.print(msg)` which is an alias for `log.info(msg)`
* Added `log.log(msg)` which is an alias for `log.info(msg)`
* Better handling of invalid JSON input #110 and #103
### 4.3.2
*Released 7/7/21*
......
......@@ -222,7 +222,17 @@ class Parser {
break
}
resolve()
} catch (e) { reject(e) }
} catch (e) {
if (e instanceof SyntaxError) {
if (e.message !== 'Unexpected end of JSON input') {
console.log(req.url, req.ip, 'JSON Parse Error: ' + e.message)
}
req.body = {}
resolve()
} else {
reject(e)
}
}
})
req.on('error', (e) => { reject(e) })
}
......
......@@ -162,13 +162,6 @@ runner.suite('Multipart', (it, suite) => {
it('should construct', () => {
Assert.isType('Multipart', new Multipart())
})
it('should accept and parse a multipart locally built request', () => {
return new Promise((resolve, reject) => {
app.post('/upload/', testUpload(resolve, reject))
const form = buildFormData()
sendUpload(form.headers, form.data, resolve, reject)
})
})
it('should accept and parse from a capture', () => {
return new Promise((resolve, reject) => {
app.post('/upload/', testUpload(resolve, reject))
......@@ -183,6 +176,13 @@ runner.suite('Multipart', (it, suite) => {
sendUpload(headers, data, resolve, reject)
})
})
it('should accept and parse a multipart locally built request', () => {
return new Promise((resolve, reject) => {
app.post('/upload/', testUpload(resolve, reject))
const form = buildFormData()
sendUpload(form.headers, form.data, resolve, reject)
})
})
it('should accept and parse from Multipart.FormBuild', () => {
return new Promise((resolve, reject) => {
app.post('/upload/', testUpload(resolve, reject))
......
......@@ -19,8 +19,12 @@
* along with Kado. If not, see <https://www.gnu.org/licenses/>.
*/
const runner = require('../lib/TestRunner').getInstance('Kado')
const Application = require('../lib/Application')
const Assert = require('../lib/Assert')
const http = require('http')
const HyperText = require('../lib/HyperText')
const Parser = require('../lib/Parser')
const PromiseMore = require('../lib/PromiseMore')
const cookieString = '_ga=GA1.2.637651231.1575923282;' +
' mm2_cookieA=06bad8dd-ecda-4e00-abbe-1e641adde6f0; _ym_d=1586356006;' +
' _ym_uid=1576356006128031579; __qca=P0-1332394709-1576356006094'
......@@ -31,7 +35,20 @@ const htmlString = '<!doctype HTML><html lang="en"><head><title>Hello World' +
const entityString = '&lt;!doctype HTML&gt;&lt;html lang=&quot;en&quot;&gt;' +
'&lt;head&gt;&lt;title&gt;Hello World&lt;/title&gt;&lt;/head&gt;' +
'&lt;body&gt;&lt;h1&gt;Hello World&lt;/h1&gt;&lt;/body&gt;&lt;/html&gt;'
runner.suite('Parser', (it) => {
runner.suite('Parser', (it, suite) => {
let app
let server
suite.before(async () => {
app = new Application()
server = new HyperText.HyperTextServer()
server.setPort(3031)
app.http.addEngine('http', server.createServer(app.router))
await app.start()
await app.listen()
})
suite.after(async () => {
await app.stop()
})
it('should parse cookies', () => {
const rv = Parser.cookie(cookieString)
Assert.isType('Object', rv)
......@@ -100,5 +117,30 @@ runner.suite('Parser', (it) => {
const rv = Parser.stringToTitle('and the dog came in')
Assert.eq(rv, 'And the Dog Came In')
})
it('should handle broken JSON', async () => {
const promise = PromiseMore.hoist()
app.post('/test/', (req, res) => { res.json(req.body) })
const client = http.request({
port: 3031,
host: 'localhost',
method: 'POST',
path: '/test/',
headers: {
'Content-Type': 'application/json'
}
})
client.on('response', (res) => {
let buf = Buffer.alloc(0)
res.on('data', (chunk) => { buf = Buffer.concat([buf, chunk]) })
res.on('end', () => {
const response = buf.toString('utf-8')
Assert.isOk(response === '{}', 'Invalid response for bad JSON input')
promise.resolve()
})
})
client.on('error', promise.reject)
client.end('{"foo":')
await promise
})
})
if (require.main === module) runner.execute().then(code => process.exit(code))
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment