Throw if the content length is too big (#1355)
This commit is contained in:
committed by
GitHub
parent
959aee5903
commit
502509cabc
@ -22,6 +22,7 @@
|
||||
const debug = require('debug')('elasticsearch')
|
||||
const os = require('os')
|
||||
const { gzip, unzip, createGzip } = require('zlib')
|
||||
const buffer = require('buffer')
|
||||
const ms = require('ms')
|
||||
const {
|
||||
ConnectionError,
|
||||
@ -35,6 +36,8 @@ const noop = () => {}
|
||||
|
||||
const clientVersion = require('../package.json').version
|
||||
const userAgent = `elasticsearch-js/${clientVersion} (${os.platform()} ${os.release()}-${os.arch()}; Node.js ${process.version})`
|
||||
const MAX_BUFFER_LENGTH = buffer.constants.MAX_LENGTH
|
||||
const MAX_STRING_LENGTH = buffer.constants.MAX_STRING_LENGTH
|
||||
|
||||
class Transport {
|
||||
constructor (opts) {
|
||||
@ -218,6 +221,22 @@ class Transport {
|
||||
|
||||
const contentEncoding = (result.headers['content-encoding'] || '').toLowerCase()
|
||||
const isCompressed = contentEncoding.indexOf('gzip') > -1 || contentEncoding.indexOf('deflate') > -1
|
||||
|
||||
/* istanbul ignore else */
|
||||
if (result.headers['content-length'] !== undefined) {
|
||||
const contentLength = Number(result.headers['content-length'])
|
||||
if (isCompressed && contentLength > MAX_BUFFER_LENGTH) {
|
||||
response.destroy()
|
||||
return onConnectionError(
|
||||
new RequestAbortedError(`The content length (${contentLength}) is bigger than the maximum allowed buffer (${MAX_BUFFER_LENGTH})`, result)
|
||||
)
|
||||
} else if (contentLength > MAX_STRING_LENGTH) {
|
||||
response.destroy()
|
||||
return onConnectionError(
|
||||
new RequestAbortedError(`The content length (${contentLength}) is bigger than the maximum allowed string (${MAX_STRING_LENGTH})`, result)
|
||||
)
|
||||
}
|
||||
}
|
||||
// if the response is compressed, we must handle it
|
||||
// as buffer for allowing decompression later
|
||||
let payload = isCompressed ? [] : ''
|
||||
|
||||
@ -21,7 +21,9 @@
|
||||
|
||||
const { test } = require('tap')
|
||||
const { URL } = require('url')
|
||||
const { Client, ConnectionPool, Transport, errors } = require('../../index')
|
||||
const buffer = require('buffer')
|
||||
const intoStream = require('into-stream')
|
||||
const { Client, ConnectionPool, Transport, Connection, errors } = require('../../index')
|
||||
const { CloudConnectionPool } = require('../../lib/pool')
|
||||
const { buildServer } = require('../utils')
|
||||
|
||||
@ -1243,3 +1245,58 @@ test('Socket destryed while reading the body', t => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
test('Content length too big (buffer)', t => {
|
||||
t.plan(4)
|
||||
|
||||
class MockConnection extends Connection {
|
||||
request (params, callback) {
|
||||
const stream = intoStream(JSON.stringify({ hello: 'world' }))
|
||||
stream.statusCode = 200
|
||||
stream.headers = {
|
||||
'content-type': 'application/json;utf=8',
|
||||
'content-encoding': 'gzip',
|
||||
'content-length': buffer.constants.MAX_LENGTH + 10,
|
||||
connection: 'keep-alive',
|
||||
date: new Date().toISOString()
|
||||
}
|
||||
stream.on('close', () => t.pass('Stream destroyed'))
|
||||
process.nextTick(callback, null, stream)
|
||||
return { abort () {} }
|
||||
}
|
||||
}
|
||||
|
||||
const client = new Client({ node: 'http://localhost:9200', Connection: MockConnection })
|
||||
client.info((err, result) => {
|
||||
t.ok(err instanceof errors.RequestAbortedError)
|
||||
t.is(err.message, `The content length (${buffer.constants.MAX_LENGTH + 10}) is bigger than the maximum allowed buffer (${buffer.constants.MAX_LENGTH})`)
|
||||
t.strictEqual(result.meta.attempts, 0)
|
||||
})
|
||||
})
|
||||
|
||||
test('Content length too big (string)', t => {
|
||||
t.plan(4)
|
||||
|
||||
class MockConnection extends Connection {
|
||||
request (params, callback) {
|
||||
const stream = intoStream(JSON.stringify({ hello: 'world' }))
|
||||
stream.statusCode = 200
|
||||
stream.headers = {
|
||||
'content-type': 'application/json;utf=8',
|
||||
'content-length': buffer.constants.MAX_STRING_LENGTH + 10,
|
||||
connection: 'keep-alive',
|
||||
date: new Date().toISOString()
|
||||
}
|
||||
stream.on('close', () => t.pass('Stream destroyed'))
|
||||
process.nextTick(callback, null, stream)
|
||||
return { abort () {} }
|
||||
}
|
||||
}
|
||||
|
||||
const client = new Client({ node: 'http://localhost:9200', Connection: MockConnection })
|
||||
client.info((err, result) => {
|
||||
t.ok(err instanceof errors.RequestAbortedError)
|
||||
t.is(err.message, `The content length (${buffer.constants.MAX_STRING_LENGTH + 10}) is bigger than the maximum allowed string (${buffer.constants.MAX_STRING_LENGTH})`)
|
||||
t.strictEqual(result.meta.attempts, 0)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user