Skip to content

Commit

Permalink
feat(rest): adds msgpack body parser
Browse files Browse the repository at this point in the history
Signed-off-by: Rifa Achrinza <[email protected]>
  • Loading branch information
achrinza committed Aug 20, 2020
1 parent 9b2a0c9 commit ed552f6
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 21 deletions.
54 changes: 36 additions & 18 deletions packages/rest/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions packages/rest/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"js-yaml": "^3.14.0",
"json-schema-compare": "^0.2.2",
"lodash": "^4.17.20",
"msgpack": "^1.0.3",
"on-finished": "^2.3.0",
"path-to-regexp": "^6.1.0",
"qs": "^6.9.4",
Expand All @@ -66,6 +67,7 @@
"@types/js-yaml": "^3.12.5",
"@types/json-schema-compare": "^0.2.0",
"@types/lodash": "^4.14.159",
"@types/msgpack": "0.0.30",
"@types/multer": "^1.4.4",
"@types/node": "^10.17.28",
"@types/on-finished": "^2.3.1",
Expand Down
2 changes: 2 additions & 0 deletions packages/rest/src/__tests__/unit/body-parser.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
UrlEncodedBodyParser,
} from '../..';
import {builtinParsers} from '../../body-parsers/body-parser.helpers';
import {MsgPackBodyParser} from '../../body-parsers/body-parser.msgpack';

describe('body parser', () => {
const defaultSchema = {
Expand Down Expand Up @@ -212,6 +213,7 @@ describe('body parser', () => {
new JsonBodyParser(options),
new UrlEncodedBodyParser(options),
new RawBodyParser(options),
new MsgPackBodyParser(),
{
name: 'xml',
supports: mediaType => true,
Expand Down
44 changes: 43 additions & 1 deletion packages/rest/src/__tests__/unit/parser.unit.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright IBM Corp. 2019. All Rights Reserved.
// Copyright IBM Corp. 2019,2020. All Rights Reserved.
// Node module: @loopback/rest
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT
Expand All @@ -15,6 +15,7 @@ import {
ShotRequestOptions,
stubExpressContext,
} from '@loopback/testlab';
import msgpack from 'msgpack';
import {
createResolvedRoute,
JsonBodyParser,
Expand Down Expand Up @@ -256,6 +257,47 @@ describe('operationArgsParser', () => {
expect(args).to.eql([{key1: ['value1', 'value2']}]);
});

it('parses body parameter for MessagePack data', async () => {
const contentTypes = [
'application/msgpack',
'application/x-msgpack',
'application/subtype+msgpack',
];

for (const contentType of contentTypes) {
const req = givenRequest({
url: '/',
headers: {
'Content-Type': contentType,
},
payload: msgpack.pack({
data: 'hello world',
}),
});

const spec = givenOperationWithRequestBody({
description: 'data',
content: {
[contentType]: {
schema: {
type: 'object',
properties: {
data: {
type: 'string',
},
},
},
},
},
});
const route = givenResolvedRoute(spec);

const args = await parseOperationArgs(req, route, requestBodyParser);

expect(args).to.eql({data: 'hello world'});
}
});

it('parses body parameter for text data', async () => {
const req = givenRequest({
url: '/',
Expand Down
3 changes: 3 additions & 0 deletions packages/rest/src/body-parsers/body-parser.helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,15 @@ export function getParserOptions(

export namespace builtinParsers {
export const json = Symbol('json');
export const msgpack = Symbol('msgpack');
export const urlencoded = Symbol('urlencoded');
export const text = Symbol('text');
export const raw = Symbol('raw');
export const stream = Symbol('stream');

export const names: (string | symbol)[] = [
json,
msgpack,
urlencoded,
text,
raw,
Expand All @@ -140,6 +142,7 @@ export namespace builtinParsers {

export const mapping: {[name: string]: symbol} = {
json,
msgpack,
urlencoded,
text,
raw,
Expand Down
4 changes: 2 additions & 2 deletions packages/rest/src/body-parsers/body-parser.json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import {inject} from '@loopback/core';
import {json} from 'body-parser';
import {is} from 'type-is';
import {RestBindings} from '../keys';
import {sanitizeJsonParse} from '../parse-json';
import {Request, RequestBodyParserOptions} from '../types';
import {
BodyParserMiddleware,
builtinParsers,
getParserOptions,
invokeBodyParserMiddleware,
builtinParsers,
} from './body-parser.helpers';
import {BodyParser, RequestBody} from './types';
import {sanitizeJsonParse} from '../parse-json';

export class JsonBodyParser implements BodyParser {
name = builtinParsers.json;
Expand Down
30 changes: 30 additions & 0 deletions packages/rest/src/body-parsers/body-parser.msgpack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright IBM Corp. 2020. All Rights Reserved.
// Node module: @loopback/rest
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import msgpack from 'msgpack';
import {is} from 'type-is';
import {Request} from '../types';
import {builtinParsers} from './body-parser.helpers';
import {BodyParser, RequestBody} from './types';

export class MsgPackBodyParser implements BodyParser {
name = builtinParsers.msgpack;

constructor() {}

supports(mediaType: string) {
return !!is(
mediaType,
'application/msgpack',
'application/x-msgpack',
'application/*+msgpack',
);
}

async parse(request: Request): Promise<RequestBody> {
const body = msgpack.unpack(request.body);
return {value: body};
}
}
7 changes: 7 additions & 0 deletions packages/rest/src/keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,13 @@ export namespace RestBindings {
bodyParserBindingKey('JsonBodyParser'),
);

/**
* Binding key for request msgpack body parser
*/
export const REQUEST_BODY_PARSER_MSGPACK = BindingKey.create<BodyParser>(
bodyParserBindingKey('MsgPackBodyParser'),
);

/**
* Binding key for request urlencoded body parser
*/
Expand Down
5 changes: 5 additions & 0 deletions packages/rest/src/rest.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
TextBodyParser,
UrlEncodedBodyParser,
} from './body-parsers';
import {MsgPackBodyParser} from './body-parsers/body-parser.msgpack';
import {RawBodyParser} from './body-parsers/body-parser.raw';
import {RestBindings, RestTags} from './keys';
import {
Expand Down Expand Up @@ -68,6 +69,10 @@ export class RestComponent implements Component {
JsonBodyParser,
RestBindings.REQUEST_BODY_PARSER_JSON,
),
createBodyParserBinding(
MsgPackBodyParser,
RestBindings.REQUEST_BODY_PARSER_MSGPACK,
),
createBodyParserBinding(
TextBodyParser,
RestBindings.REQUEST_BODY_PARSER_TEXT,
Expand Down

0 comments on commit ed552f6

Please sign in to comment.