Example #1
0
    it('parses multipart file with annotation', async () => {

        const body =
            '--AaB03x\r\n' +
            'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n' +
            'Content-Type: image/jpeg\r\n' +
            '\r\n' +
            '... contents of file1.txt ...\r\r\n' +
            '--AaB03x--\r\n';

        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-type': 'multipart/form-data; boundary="AaB03x"'
        };

        const { payload } = await Subtext.parse(request, null, { parse: true, output: 'data', multipart: { output: 'annotated' } });
        expect(payload.pics).to.equal({
            payload: Buffer.from('... contents of file1.txt ...\r'),
            headers: {
                'content-disposition': 'form-data; name="pics"; filename="file1.txt"',
                'content-type': 'image/jpeg'
            },
            filename: 'file1.txt'
        });
    });
Example #2
0
    it('errors on invalid upload directory (parse true)', async () => {

        const request = Wreck.toReadableStream('payload');
        request.headers = {
            'content-type': 'application/json'
        };

        await expect(Subtext.parse(request, null, { parse: true, output: 'file', uploads: '/a/b/c/no/such/folder' })).to.reject(/ENOENT/);
    });
Example #3
0
    it('returns null on empty payload and application/octet-stream', async () => {

        const body = '';
        const request = Wreck.toReadableStream(body);
        request.headers = {};

        const { payload, mime } = await Subtext.parse(request, null, { parse: true, output: 'data' });
        expect(mime).to.equal('application/octet-stream');
        expect(payload).to.be.null();
    });
Example #4
0
File: index.js Project: hapijs/ammo
    it('emits error on internal processing errors', async () => {

        const random = Buffer.alloc(5000);
        const source = Wreck.toReadableStream(random);
        const stream = new Ammo.Stream({ from: 1000, to: 4000 });

        stream._range = null;         // Force a processing error

        await expect(Wreck.read(source.pipe(stream))).to.reject(Error);
    });
Example #5
0
File: index.js Project: hapijs/ammo
    it('returns a subset of a stream', async () => {

        const random = Buffer.alloc(5000);
        const source = Wreck.toReadableStream(random);
        const range = Ammo.header('bytes=1000-4000', 5000);
        const stream = new Ammo.Stream(range[0]);

        const buffer = await Wreck.read(source.pipe(stream));
        expect(buffer.toString()).to.equal(random.slice(1000, 4001).toString());
    });
Example #6
0
    it('errors on invalid content type header', async () => {

        const body = '{"x":"1","y":"2","z":"3"}';
        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-type': 'steve'
        };

        await expect(Subtext.parse(request, null, { parse: true, output: 'data' })).to.reject('Invalid content-type header');
    });
Example #7
0
    it('errors on unsupported content type', async () => {

        const body = '{"x":"1","y":"2","z":"3"}';
        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-type': 'james/bond'
        };

        await expect(Subtext.parse(request, null, { parse: true, output: 'data' })).to.reject('Unsupported Media Type');
    });
Example #8
0
    it('errors on an unallowed content-type (array)', async () => {

        const body = '{"x":"1","y":"2","z":"3"}';
        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-type': 'text/plain'
        };

        await expect(Subtext.parse(request, null, { parse: true, output: 'data', allow: ['application/json'] })).to.reject('Unsupported Media Type');
    });
Example #9
0
    it('custom default content-type', async () => {

        const body = '{"x":"1","y":"2","z":"3"}';
        const request = Wreck.toReadableStream(body);
        request.headers = {};

        const { payload, mime } = await Subtext.parse(request, null, { parse: true, output: 'data', defaultContentType: 'application/json' });
        expect(mime).to.equal('application/json');
        expect(payload).to.equal(JSON.parse(body));
    });
Example #10
0
    it('defaults to application/octet-stream', async () => {

        const body = '{"x":"1","y":"2","z":"3"}';
        const request = Wreck.toReadableStream(body);
        request.headers = {};

        const { payload, mime } = await Subtext.parse(request, null, { parse: true, output: 'data' });
        expect(mime).to.equal('application/octet-stream');
        expect(Buffer.isBuffer(payload)).to.be.true();
        expect(payload.toString()).to.equal(body);
    });
Example #11
0
    it('returns an empty string', async () => {

        const body = '';
        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-type': 'text/plain'
        };

        const { payload } = await Subtext.parse(request, null, { parse: true, output: 'data' });
        expect(payload).to.equal('');
    });
Example #12
0
    it('errors on invalid JSON payload (__proto__)', async () => {

        const body = '{"x":1,"y":2,"z":3,"__proto__":{"a":1}}';
        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-type': 'application/json'
        };

        const err = await expect(Subtext.parse(request, null, { parse: true, output: 'data' })).to.reject('Invalid request payload JSON format');
        expect(err.raw.toString()).to.equal(body);
    });
Example #13
0
    it('validates maxBytes when content is within limit', async () => {

        const body = '{"x":"1","y":"2","z":"3"}';
        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-length': '50',
            'content-type': 'application/json'
        };

        await expect(Subtext.parse(request, null, { parse: false, output: 'data', maxBytes: 100 })).to.not.reject();
    });
Example #14
0
    it('limits maxBytes when content-length header missing', async () => {

        const body = '{"x":"1","y":"2","z":"3"}';
        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-type': 'application/json'
        };
        request.destroy = function () { };

        await expect(Subtext.parse(request, null, { parse: false, output: 'data', maxBytes: 10 })).to.reject('Payload content length greater than maximum allowed: 10');
    });
Example #15
0
    it('errors when content-length header greater than maxBytes', async () => {

        const body = '{"x":"1","y":"2","z":"3"}';
        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-length': '50',
            'content-type': 'application/json'
        };

        const err = await expect(Subtext.parse(request, null, { parse: false, output: 'data', maxBytes: 10 })).to.reject('Payload content length greater than maximum allowed: 10');
        expect(err.output.statusCode).to.equal(413);
    });
Example #16
0
    it('parses an allowed content-type (array)', async () => {

        const body = '{"x":"1","y":"2","z":"3"}';
        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-type': 'text/plain'
        };

        const { payload, mime } = await Subtext.parse(request, null, { parse: true, output: 'data', allow: ['text/plain'] });
        expect(mime).to.equal('text/plain');
        expect(payload).to.equal(body);
    });
Example #17
0
    it('returns an empty parsed body', async () => {

        const body = '';
        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-type': 'application/json'
        };

        const { payload, mime } = await Subtext.parse(request, null, { parse: true, output: 'data' });
        expect(mime).to.equal('application/json');
        expect(payload).to.equal(null);
    });
Example #18
0
    it('errors on malformed zipped payload (parse gunzip only)', async () => {

        const body = '7d8d78347h8347d58w347hd58w374d58w37h5d8w37hd4';
        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-encoding': 'gzip',
            'content-type': 'application/json'
        };

        const err = await expect(Subtext.parse(request, null, { parse: 'gunzip', output: 'data' })).to.reject('Invalid compressed payload');
        expect(err.output.statusCode).to.equal(400);
    });
Example #19
0
    it('removes __proto__ from input', async () => {

        const body = '{"x":1,"y":2,"z":3,"__proto__":{"a":1}}';
        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-type': 'application/json'
        };

        const { payload, mime } = await Subtext.parse(request, null, { parse: true, output: 'data', protoAction: 'remove' });
        expect(mime).to.equal('application/json');
        expect(payload).to.equal({ x: 1, y: 2, z: 3 });
    });
Example #20
0
    it('returns a parsed body (json-derived media type)', async () => {

        const body = '{"x":"1","y":"2","z":"3"}';
        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-type': 'application/json-patch+json'
        };

        const { payload, mime } = await Subtext.parse(request, null, { parse: true, output: 'data' });
        expect(mime).to.equal('application/json-patch+json');
        expect(payload).to.equal(JSON.parse(body));
    });
Example #21
0
    it('parses empty form encoded payload', async () => {

        const body = '';
        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-type': 'application/x-www-form-urlencoded'
        };

        const { payload, mime } = await Subtext.parse(request, null, { parse: true, output: 'data' });
        expect(mime).to.equal('application/x-www-form-urlencoded');
        expect(payload).to.equal({});
    });
Example #22
0
    it('returns a raw body', async () => {

        const body = '{"x":"1","y":"2","z":"3"}';
        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-type': 'application/json'
        };

        const { payload, mime } = await Subtext.parse(request, null, { parse: false, output: 'data' });
        expect(mime).to.equal('application/json');
        expect(Buffer.isBuffer(payload)).to.be.true();
        expect(payload.toString()).to.equal(body);
    });
Example #23
0
    it('deflates payload without parsing', async () => {

        const body = '{"x":"1","y":"2","z":"3"}';
        const compressed = await internals.compress('deflate', body);
        const request = Wreck.toReadableStream(compressed);
        request.headers = {
            'content-encoding': 'deflate',
            'content-type': 'application/json'
        };

        const { payload } = await Subtext.parse(request, null, { parse: 'gunzip', output: 'data' });
        expect(payload.toString()).to.equal(body);
    });
Example #24
0
    it('returns a raw body as stream', async () => {

        const body = '{"x":"1","y":"2","z":"3"}';
        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-type': 'application/json'
        };

        const { payload: stream, mime } = await Subtext.parse(request, null, { parse: false, output: 'stream' });
        expect(mime).to.equal('application/json');
        const payload = await Wreck.read(stream);
        expect(payload.toString()).to.equal(body);
    });
Example #25
0
    it('unzips payload without parsing (external decoders)', async () => {

        const body = '{"x":"1","y":"2","z":"3"}';
        const compressed = await internals.compress('gzip', body);
        const request = Wreck.toReadableStream(compressed);
        request.headers = {
            'content-encoding': 'gzip',
            'content-type': 'application/json'
        };

        const { payload } = await Subtext.parse(request, null, { parse: 'gunzip', output: 'data', compression: {}, decoders: { gzip: (options) => Zlib.createGunzip(options) } });
        expect(payload.toString()).to.equal(body);
    });
Example #26
0
    it('parses a gzipped payload', async () => {

        const body = '{"x":"1","y":"2","z":"3"}';
        const compressed = await internals.compress('gzip', body);
        const request = Wreck.toReadableStream(compressed);
        request.headers = {
            'content-encoding': 'gzip',
            'content-type': 'application/json'
        };

        const { payload } = await Subtext.parse(request, null, { parse: true, output: 'data' });
        expect(payload).to.equal(JSON.parse(body));
    });
Example #27
0
    it('saves file', async () => {

        const request = Wreck.toReadableStream('payload');
        request.headers = {
            'content-type': 'application/json'
        };

        const { payload } = await Subtext.parse(request, null, { parse: false, output: 'file' });
        expect(payload).to.only.contain(['path', 'bytes']);
        const receivedContents = Fs.readFileSync(payload.path);
        Fs.unlinkSync(payload.path);
        expect(receivedContents.toString()).to.equal('payload');
    });
Example #28
0
    it('peeks at multipart in stream mode', async () => {

        const body =
            '--AaB03x\r\n' +
            'content-disposition: form-data; name="x"\r\n' +
            '\r\n' +
            'First\r\n' +
            '--AaB03x\r\n' +
            'content-disposition: form-data; name="x"\r\n' +
            '\r\n' +
            'Second\r\n' +
            '--AaB03x\r\n' +
            'content-disposition: form-data; name="x"\r\n' +
            '\r\n' +
            'Third\r\n' +
            '--AaB03x\r\n' +
            'content-disposition: form-data; name="field1"\r\n' +
            '\r\n' +
            'Joe Blow\r\nalmost tricked you!\r\n' +
            '--AaB03x\r\n' +
            'content-disposition: form-data; name="field1"\r\n' +
            '\r\n' +
            'Repeated name segment\r\n' +
            '--AaB03x\r\n' +
            'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n' +
            'Content-Type: text/plain\r\n' +
            '\r\n' +
            '... contents of file1.txt ...\r\r\n' +
            '--AaB03x--\r\n';

        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-type': 'multipart/form-data; boundary=AaB03x'
        };

        let raw = '';
        const tap = new Stream.Transform();
        tap._transform = function (chunk, encoding, callback) {

            raw = raw + chunk.toString();
            this.push(chunk, encoding);
            callback();
        };

        const { payload } = await Subtext.parse(request, tap, { parse: true, output: 'stream' });
        expect(payload.x).to.equal(['First', 'Second', 'Third']);
        expect(payload.field1).to.equal(['Joe Blow\r\nalmost tricked you!', 'Repeated name segment']);
        expect(payload.pics.hapi.filename).to.equal('file1.txt');
        expect(raw).to.equal(body);
    });
Example #29
0
    it('errors on an invalid multipart payload', async () => {

        const body =
            '--AaB03x\r\n' +
            'content-disposition: form-data; name="x"\r\n' +
            '\r\n' +
            'First\r\n';

        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-type': 'multipart/form-data; boundary=AaB03x'
        };

        await expect(Subtext.parse(request, null, { parse: true, output: 'data' })).to.reject('Invalid multipart payload format');
    });
Example #30
0
    it('errors on invalid uploads folder while processing multipart payload', async () => {

        const body =
            '--AaB03x\r\n' +
            'content-disposition: form-data; name="pics"; filename="file1.txt"\r\n' +
            '\r\n' +
            '... contents of file1.txt ...\r\r\n' +
            '--AaB03x--\r\n';

        const request = Wreck.toReadableStream(body);
        request.headers = {
            'content-type': 'multipart/form-data; boundary="AaB03x"'
        };

        await expect(Subtext.parse(request, null, { parse: true, output: 'file', uploads: '/no/such/folder/a/b/c' })).to.reject(/\/no\/such\/folder\/a\/b\/c/);
    });