diff options
Diffstat (limited to 'test/content-length.js')
-rw-r--r-- | test/content-length.js | 445 |
1 files changed, 445 insertions, 0 deletions
diff --git a/test/content-length.js b/test/content-length.js new file mode 100644 index 0000000..9ce7405 --- /dev/null +++ b/test/content-length.js @@ -0,0 +1,445 @@ +'use strict' + +const { test } = require('tap') +const { Client, errors } = require('..') +const { createServer } = require('http') +const { Readable } = require('stream') +const { maybeWrapStream, consts } = require('./utils/async-iterators') + +test('request invalid content-length', (t) => { + t.plan(7) + + const server = createServer((req, res) => { + res.end() + }) + t.teardown(server.close.bind(server)) + server.listen(0, () => { + const client = new Client(`http://localhost:${server.address().port}`) + t.teardown(client.destroy.bind(client)) + + client.request({ + path: '/', + method: 'PUT', + headers: { + 'content-length': 10 + }, + body: 'asd' + }, (err, data) => { + t.type(err, errors.RequestContentLengthMismatchError) + }) + + client.request({ + path: '/', + method: 'PUT', + headers: { + 'content-length': 10 + }, + body: 'asdasdasdasdasdasda' + }, (err, data) => { + t.type(err, errors.RequestContentLengthMismatchError) + }) + + client.request({ + path: '/', + method: 'PUT', + headers: { + 'content-length': 10 + }, + body: Buffer.alloc(9) + }, (err, data) => { + t.type(err, errors.RequestContentLengthMismatchError) + }) + + client.request({ + path: '/', + method: 'PUT', + headers: { + 'content-length': 10 + }, + body: Buffer.alloc(11) + }, (err, data) => { + t.type(err, errors.RequestContentLengthMismatchError) + }) + + client.request({ + path: '/', + method: 'GET', + headers: { + 'content-length': 4 + }, + body: ['asd'] + }, (err, data) => { + t.type(err, errors.RequestContentLengthMismatchError) + }) + + client.request({ + path: '/', + method: 'GET', + headers: { + 'content-length': 4 + }, + body: ['asasdasdasdd'] + }, (err, data) => { + t.type(err, errors.RequestContentLengthMismatchError) + }) + + client.request({ + path: '/', + method: 'DELETE', + headers: { + 'content-length': 4 + }, + body: ['asasdasdasdd'] + }, (err, data) => { + t.type(err, errors.RequestContentLengthMismatchError) + }) + }) +}) + +function invalidContentLength (bodyType) { + test(`request streaming ${bodyType} invalid content-length`, (t) => { + t.plan(4) + + const server = createServer((req, res) => { + res.end() + }) + t.teardown(server.close.bind(server)) + server.listen(0, () => { + const client = new Client(`http://localhost:${server.address().port}`) + t.teardown(client.destroy.bind(client)) + + client.once('disconnect', () => { + t.pass() + client.once('disconnect', () => { + t.pass() + }) + }) + + client.request({ + path: '/', + method: 'PUT', + headers: { + 'content-length': 10 + }, + body: maybeWrapStream(new Readable({ + read () { + setImmediate(() => { + this.push('asdasdasdkajsdnasdkjasnd') + this.push(null) + }) + } + }), bodyType) + }, (err, data) => { + t.type(err, errors.RequestContentLengthMismatchError) + }) + + client.request({ + path: '/', + method: 'PUT', + headers: { + 'content-length': 10 + }, + body: maybeWrapStream(new Readable({ + read () { + setImmediate(() => { + this.push('asd') + this.push(null) + }) + } + }), bodyType) + }, (err, data) => { + t.type(err, errors.RequestContentLengthMismatchError) + }) + }) + }) +} + +invalidContentLength(consts.STREAM) +invalidContentLength(consts.ASYNC_ITERATOR) + +function zeroContentLength (bodyType) { + test(`request ${bodyType} streaming data when content-length=0`, (t) => { + t.plan(1) + + const server = createServer((req, res) => { + res.end() + }) + t.teardown(server.close.bind(server)) + server.listen(0, () => { + const client = new Client(`http://localhost:${server.address().port}`) + t.teardown(client.destroy.bind(client)) + + client.request({ + path: '/', + method: 'PUT', + headers: { + 'content-length': 0 + }, + body: maybeWrapStream(new Readable({ + read () { + setImmediate(() => { + this.push('asdasdasdkajsdnasdkjasnd') + this.push(null) + }) + } + }), bodyType) + }, (err, data) => { + t.type(err, errors.RequestContentLengthMismatchError) + }) + }) + }) +} + +zeroContentLength(consts.STREAM) +zeroContentLength(consts.ASYNC_ITERATOR) + +test('request streaming no body data when content-length=0', (t) => { + t.plan(2) + + const server = createServer((req, res) => { + req.pipe(res) + }) + t.teardown(server.close.bind(server)) + server.listen(0, () => { + const client = new Client(`http://localhost:${server.address().port}`) + t.teardown(client.destroy.bind(client)) + + client.request({ + path: '/', + method: 'PUT', + headers: { + 'content-length': 0 + } + }, (err, data) => { + t.error(err) + data.body + .on('data', () => { + t.fail() + }) + .on('end', () => { + t.pass() + }) + }) + }) +}) + +test('response invalid content length with close', (t) => { + t.plan(3) + + const server = createServer((req, res) => { + res.writeHead(200, { + 'content-length': 10 + }) + res.end('123') + }) + t.teardown(server.close.bind(server)) + server.listen(0, () => { + const client = new Client(`http://localhost:${server.address().port}`, { + pipelining: 0 + }) + t.teardown(client.destroy.bind(client)) + + client.on('disconnect', (origin, client, err) => { + t.equal(err.code, 'UND_ERR_RES_CONTENT_LENGTH_MISMATCH') + }) + + client.request({ + path: '/', + method: 'GET' + }, (err, data) => { + t.error(err) + data.body + .on('end', () => { + t.fail() + }) + .on('error', (err) => { + t.equal(err.code, 'UND_ERR_RES_CONTENT_LENGTH_MISMATCH') + }) + .resume() + }) + }) +}) + +test('request streaming with Readable.from(buf)', (t) => { + const server = createServer((req, res) => { + req.pipe(res) + }) + t.teardown(server.close.bind(server)) + server.listen(0, () => { + const client = new Client(`http://localhost:${server.address().port}`) + t.teardown(client.destroy.bind(client)) + + client.request({ + path: '/', + method: 'PUT', + body: Readable.from(Buffer.from('hello')) + }, (err, data) => { + const chunks = [] + t.error(err) + data.body + .on('data', (chunk) => { + chunks.push(chunk) + }) + .on('end', () => { + t.equal(Buffer.concat(chunks).toString(), 'hello') + t.pass() + t.end() + }) + }) + }) +}) + +test('request DELETE, content-length=0, with body', (t) => { + t.plan(5) + const server = createServer((req, res) => { + res.end() + }) + server.on('request', (req, res) => { + t.equal(req.headers['content-length'], undefined) + }) + t.teardown(server.close.bind(server)) + server.listen(0, () => { + const client = new Client(`http://localhost:${server.address().port}`) + t.teardown(client.destroy.bind(client)) + + client.request({ + path: '/', + method: 'DELETE', + headers: { + 'content-length': 0 + }, + body: new Readable({ + read () { + this.push('asd') + this.push(null) + } + }) + }, (err) => { + t.type(err, errors.RequestContentLengthMismatchError) + }) + + client.request({ + path: '/', + method: 'DELETE', + headers: { + 'content-length': 0 + } + }, (err, resp) => { + t.equal(resp.headers['content-length'], '0') + t.error(err) + }) + + client.on('disconnect', () => { + t.pass() + }) + }) +}) + +test('content-length shouldSendContentLength=false', (t) => { + t.plan(15) + const server = createServer((req, res) => { + res.end() + }) + server.on('request', (req, res) => { + switch (req.url) { + case '/put0': + t.equal(req.headers['content-length'], '0') + break + case '/head': + t.equal(req.headers['content-length'], undefined) + break + case '/get': + t.equal(req.headers['content-length'], undefined) + break + } + }) + t.teardown(server.close.bind(server)) + server.listen(0, () => { + const client = new Client(`http://localhost:${server.address().port}`) + t.teardown(client.destroy.bind(client)) + + client.request({ + path: '/put0', + method: 'PUT', + headers: { + 'content-length': 0 + } + }, (err, resp) => { + t.equal(resp.headers['content-length'], '0') + t.error(err) + }) + + client.request({ + path: '/head', + method: 'HEAD', + headers: { + 'content-length': 10 + } + }, (err, resp) => { + t.equal(resp.headers['content-length'], undefined) + t.error(err) + }) + + client.request({ + path: '/get', + method: 'GET', + headers: { + 'content-length': 0 + } + }, (err) => { + t.error(err) + }) + + client.request({ + path: '/', + method: 'GET', + headers: { + 'content-length': 4 + }, + body: new Readable({ + read () { + this.push('asd') + this.push(null) + } + }) + }, (err) => { + t.error(err) + }) + + client.request({ + path: '/', + method: 'GET', + headers: { + 'content-length': 4 + }, + body: new Readable({ + read () { + this.push('asasdasdasdd') + this.push(null) + } + }) + }, (err) => { + t.error(err) + }) + + client.request({ + path: '/', + method: 'HEAD', + headers: { + 'content-length': 4 + }, + body: new Readable({ + read () { + this.push('asasdasdasdd') + this.push(null) + } + }) + }, (err) => { + t.error(err) + }) + + client.on('disconnect', () => { + t.pass() + }) + }) +}) |