Skip to content

Commit ed552f6

Browse files
committed
feat(rest): adds msgpack body parser
Signed-off-by: Rifa Achrinza <25147899+achrinza@users.noreply.github.com>
1 parent 9b2a0c9 commit ed552f6

File tree

9 files changed

+130
-21
lines changed

9 files changed

+130
-21
lines changed

packages/rest/package-lock.json

Lines changed: 36 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/rest/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"js-yaml": "^3.14.0",
4949
"json-schema-compare": "^0.2.2",
5050
"lodash": "^4.17.20",
51+
"msgpack": "^1.0.3",
5152
"on-finished": "^2.3.0",
5253
"path-to-regexp": "^6.1.0",
5354
"qs": "^6.9.4",
@@ -66,6 +67,7 @@
6667
"@types/js-yaml": "^3.12.5",
6768
"@types/json-schema-compare": "^0.2.0",
6869
"@types/lodash": "^4.14.159",
70+
"@types/msgpack": "0.0.30",
6971
"@types/multer": "^1.4.4",
7072
"@types/node": "^10.17.28",
7173
"@types/on-finished": "^2.3.1",

packages/rest/src/__tests__/unit/body-parser.unit.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
UrlEncodedBodyParser,
2323
} from '../..';
2424
import {builtinParsers} from '../../body-parsers/body-parser.helpers';
25+
import {MsgPackBodyParser} from '../../body-parsers/body-parser.msgpack';
2526

2627
describe('body parser', () => {
2728
const defaultSchema = {
@@ -212,6 +213,7 @@ describe('body parser', () => {
212213
new JsonBodyParser(options),
213214
new UrlEncodedBodyParser(options),
214215
new RawBodyParser(options),
216+
new MsgPackBodyParser(),
215217
{
216218
name: 'xml',
217219
supports: mediaType => true,

packages/rest/src/__tests__/unit/parser.unit.ts

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright IBM Corp. 2019. All Rights Reserved.
1+
// Copyright IBM Corp. 2019,2020. All Rights Reserved.
22
// Node module: @loopback/rest
33
// This file is licensed under the MIT License.
44
// License text available at https://opensource.org/licenses/MIT
@@ -15,6 +15,7 @@ import {
1515
ShotRequestOptions,
1616
stubExpressContext,
1717
} from '@loopback/testlab';
18+
import msgpack from 'msgpack';
1819
import {
1920
createResolvedRoute,
2021
JsonBodyParser,
@@ -256,6 +257,47 @@ describe('operationArgsParser', () => {
256257
expect(args).to.eql([{key1: ['value1', 'value2']}]);
257258
});
258259

260+
it('parses body parameter for MessagePack data', async () => {
261+
const contentTypes = [
262+
'application/msgpack',
263+
'application/x-msgpack',
264+
'application/subtype+msgpack',
265+
];
266+
267+
for (const contentType of contentTypes) {
268+
const req = givenRequest({
269+
url: '/',
270+
headers: {
271+
'Content-Type': contentType,
272+
},
273+
payload: msgpack.pack({
274+
data: 'hello world',
275+
}),
276+
});
277+
278+
const spec = givenOperationWithRequestBody({
279+
description: 'data',
280+
content: {
281+
[contentType]: {
282+
schema: {
283+
type: 'object',
284+
properties: {
285+
data: {
286+
type: 'string',
287+
},
288+
},
289+
},
290+
},
291+
},
292+
});
293+
const route = givenResolvedRoute(spec);
294+
295+
const args = await parseOperationArgs(req, route, requestBodyParser);
296+
297+
expect(args).to.eql({data: 'hello world'});
298+
}
299+
});
300+
259301
it('parses body parameter for text data', async () => {
260302
const req = givenRequest({
261303
url: '/',

packages/rest/src/body-parsers/body-parser.helpers.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,15 @@ export function getParserOptions(
125125

126126
export namespace builtinParsers {
127127
export const json = Symbol('json');
128+
export const msgpack = Symbol('msgpack');
128129
export const urlencoded = Symbol('urlencoded');
129130
export const text = Symbol('text');
130131
export const raw = Symbol('raw');
131132
export const stream = Symbol('stream');
132133

133134
export const names: (string | symbol)[] = [
134135
json,
136+
msgpack,
135137
urlencoded,
136138
text,
137139
raw,
@@ -140,6 +142,7 @@ export namespace builtinParsers {
140142

141143
export const mapping: {[name: string]: symbol} = {
142144
json,
145+
msgpack,
143146
urlencoded,
144147
text,
145148
raw,

packages/rest/src/body-parsers/body-parser.json.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ import {inject} from '@loopback/core';
77
import {json} from 'body-parser';
88
import {is} from 'type-is';
99
import {RestBindings} from '../keys';
10+
import {sanitizeJsonParse} from '../parse-json';
1011
import {Request, RequestBodyParserOptions} from '../types';
1112
import {
1213
BodyParserMiddleware,
14+
builtinParsers,
1315
getParserOptions,
1416
invokeBodyParserMiddleware,
15-
builtinParsers,
1617
} from './body-parser.helpers';
1718
import {BodyParser, RequestBody} from './types';
18-
import {sanitizeJsonParse} from '../parse-json';
1919

2020
export class JsonBodyParser implements BodyParser {
2121
name = builtinParsers.json;
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright IBM Corp. 2020. All Rights Reserved.
2+
// Node module: @loopback/rest
3+
// This file is licensed under the MIT License.
4+
// License text available at https://opensource.org/licenses/MIT
5+
6+
import msgpack from 'msgpack';
7+
import {is} from 'type-is';
8+
import {Request} from '../types';
9+
import {builtinParsers} from './body-parser.helpers';
10+
import {BodyParser, RequestBody} from './types';
11+
12+
export class MsgPackBodyParser implements BodyParser {
13+
name = builtinParsers.msgpack;
14+
15+
constructor() {}
16+
17+
supports(mediaType: string) {
18+
return !!is(
19+
mediaType,
20+
'application/msgpack',
21+
'application/x-msgpack',
22+
'application/*+msgpack',
23+
);
24+
}
25+
26+
async parse(request: Request): Promise<RequestBody> {
27+
const body = msgpack.unpack(request.body);
28+
return {value: body};
29+
}
30+
}

packages/rest/src/keys.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,13 @@ export namespace RestBindings {
127127
bodyParserBindingKey('JsonBodyParser'),
128128
);
129129

130+
/**
131+
* Binding key for request msgpack body parser
132+
*/
133+
export const REQUEST_BODY_PARSER_MSGPACK = BindingKey.create<BodyParser>(
134+
bodyParserBindingKey('MsgPackBodyParser'),
135+
);
136+
130137
/**
131138
* Binding key for request urlencoded body parser
132139
*/

packages/rest/src/rest.component.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
TextBodyParser,
2525
UrlEncodedBodyParser,
2626
} from './body-parsers';
27+
import {MsgPackBodyParser} from './body-parsers/body-parser.msgpack';
2728
import {RawBodyParser} from './body-parsers/body-parser.raw';
2829
import {RestBindings, RestTags} from './keys';
2930
import {
@@ -68,6 +69,10 @@ export class RestComponent implements Component {
6869
JsonBodyParser,
6970
RestBindings.REQUEST_BODY_PARSER_JSON,
7071
),
72+
createBodyParserBinding(
73+
MsgPackBodyParser,
74+
RestBindings.REQUEST_BODY_PARSER_MSGPACK,
75+
),
7176
createBodyParserBinding(
7277
TextBodyParser,
7378
RestBindings.REQUEST_BODY_PARSER_TEXT,

0 commit comments

Comments
 (0)