Skip to content
This repository has been archived by the owner on Jul 2, 2020. It is now read-only.

fix: fix post in fc apigw and add more test case #181

Merged
merged 2 commits into from
Jun 28, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions packages/serverless-http-parser/src/http/req.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,18 @@ export class HTTPRequest {
}

get body() {
let body = this[EVENT].body;
if (this[EVENT].isBase64Encoded === 'true') {
return Buffer.from(body, 'base64').toString();
}

if (this.bodyParsed) {
return this[BODY];
}

let body = this[EVENT].body;
if (
this[EVENT].isBase64Encoded === 'true' ||
this[EVENT].isBase64Encoded === true
) {
body = Buffer.from(body, 'base64').toString();
}

if (Buffer.isBuffer(body)) {
body = Buffer.from(body).toString();
}
Expand All @@ -113,9 +116,14 @@ export class HTTPRequest {
break;
case 'urlencoded':
try {
this[BODY] = qs.parse(body);
// fc apigw use this
this[BODY] = JSON.parse(body);
} catch {
throw new Error('invalid urlencoded received');
try {
this[BODY] = qs.parse(body);
} catch (err) {
throw new Error('invalid urlencoded received');
}
}
break;
default:
Expand Down
2 changes: 1 addition & 1 deletion packages/serverless-http-parser/src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export interface FCAPIGatewayEvent {
queryParameters: object;
pathParameters: object;
body: string;
isBase64Encoded: 'true' | 'false';
isBase64Encoded: 'true' | 'false' | boolean;
}

export interface FCHTTPEvent {
Expand Down
10 changes: 6 additions & 4 deletions packages/serverless-http-parser/src/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,18 @@ export const request = {
},

get body() {
if (this.req.bodyParsed) {
return this.req.body;
if (this[BODY]) {
return this[BODY];
}

let body = this.req.body;

if (this[BODY]) {
if (this.req.bodyParsed) {
// api 网关会被 parse,这里就直接返回了
this[BODY] = this.req.body;
return this[BODY];
}

// fc http parser 会走到这里,因为 req.body 是 buffer,且不会被处理
if (Buffer.isBuffer(body)) {
body = Buffer.from(body).toString();
}
Expand Down
103 changes: 103 additions & 0 deletions packages/serverless-http-parser/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,109 @@ describe('test http parser', () => {
);
});

describe('test aliyun apigw post type', () => {
it('should parse text/html and got string body', () => {
const app = new Application();
const req = new HTTPRequest(
require('./resource/fc_apigw_post_text.json'),
require('./resource/fc_ctx.json')
);
const res = new HTTPResponse();
const context = app.createContext(req, res);

// alias
assert(context.req !== context.request);
assert(context.res !== context.response);
assert(context.header === context.headers);
assert(context.headers === context.req.headers);

// request
assert(context.method === 'POST');
assert(context.request.method === 'POST');
assert(context.path === '/api/321');
assert(context.request.path === '/api/321');

// test parser body, it's string because content-type is text/html
assert(context.request.body === '{"c":"b"}');
});

it('should parse application/json and got json body', () => {
const app = new Application();
const req = new HTTPRequest(
require('./resource/fc_apigw_post_json.json'),
require('./resource/fc_ctx.json')
);
const res = new HTTPResponse();
const context = app.createContext(req, res);

// alias
assert(context.req !== context.request);
assert(context.res !== context.response);
assert(context.header === context.headers);
assert(context.headers === context.req.headers);

// request
assert(context.method === 'POST');
assert(context.request.method === 'POST');
assert(context.path === '/api/321');
assert(context.request.path === '/api/321');

// test parser body, it's string because content-type is text/html
assert.deepStrictEqual(context.request.body, { c: 'b' });
});

it('should parse form-urlencoded and got json body', () => {
const app = new Application();
const req = new HTTPRequest(
require('./resource/fc_apigw_post_form.json'),
require('./resource/fc_ctx.json')
);
const res = new HTTPResponse();
const context = app.createContext(req, res);

// alias
assert(context.req !== context.request);
assert(context.res !== context.response);
assert(context.header === context.headers);
assert(context.headers === context.req.headers);

// request
assert(context.method === 'POST');
assert(context.request.method === 'POST');
assert(context.path === '/api/321');
assert(context.request.path === '/api/321');

// test parser body, it's string because content-type is text/html
assert.deepStrictEqual(context.request.body, { c: 'b' });
});

it('should parse json by gw filter', () => {
// 网关过滤后的结果
const app = new Application();
const req = new HTTPRequest(
require('./resource/fc_apigw_post_gw_filter.json'),
require('./resource/fc_ctx.json')
);
const res = new HTTPResponse();
const context = app.createContext(req, res);

// alias
assert(context.req !== context.request);
assert(context.res !== context.response);
assert(context.header === context.headers);
assert(context.headers === context.req.headers);

// request
assert(context.method === 'POST');
assert(context.request.method === 'POST');
assert(context.path === '/api/321');
assert(context.request.path === '/api/321');

// test parser body, it's string because content-type is text/html
assert.deepStrictEqual(context.request.body, '{"c":"b"}');
});
});

it('should test callback', async () => {
const app = new Application();
app.use(async (ctx, next) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"body": "{\"c\":\"b\"}",
"headers": {
"accept": "*/*",
"cache-control": "no-cache",
"user-agent": "PostmanRuntime/7.24.1",
"postman-token": "feb51b11-9103-463a-92ff-73076d37b683",
"accept-encoding": "gzip, deflate, br",
"content-type": "application/x-www-form-urlencoded"
},
"httpMethod": "POST",
"isBase64Encoded": false,
"path": "/api/321",
"pathParameters": {
"userId": "321"
},
"queryParameters": {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"body": "eyJjIjoiYiJ9",
"headers": {
"X-Ca-Dashboard-Action": "DEBUG",
"X-Ca-Dashboard-Uid": "111111",
"X-Ca-Dashboard-Role": "USER"
},
"httpMethod": "POST",
"isBase64Encoded": true,
"path": "/api/321",
"pathParameters": {
"userId": "321"
},
"queryParameters": {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"body": "eyJjIjoiYiJ9",
"headers": {
"X-Ca-Dashboard-Action": "DEBUG",
"X-Ca-Dashboard-Uid": "125087",
"X-Ca-Stage": "RELEASE",
"X-Ca-Dashboard-Role": "USER",
"User-Agent": "Apache-HttpClient/4.5.6 (Java/1.8.0_172)",
"Accept-Encoding": "gzip,deflate",
"Content-MD5": "Kry+hjKjc2lvIrwoJqdY9Q==",
"Content-Type": "application/json; charset=utf-8"
},
"httpMethod": "POST",
"isBase64Encoded": true,
"path": "/api/321",
"pathParameters": {
"userId": "321"
},
"queryParameters": {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"body": "eyJjIjoiYiJ9",
"headers": {
"x-ca-dashboard-action": "DEBUG",
"x-ca-dashboard-uid": "125087",
"x-ca-stage": "RELEASE",
"x-ca-dashboard-role": "USER",
"user-agent": "Apache-HttpClient/4.5.6 (Java/1.8.0_172)",
"accept-encoding": "gzip,deflate",
"content-md5": "Kry+hjKjc2lvIrwoJqdY9Q==",
"content-type": "text/html; charset=utf-8"
},
"httpMethod": "POST",
"isBase64Encoded": true,
"path": "/api/321",
"pathParameters": {
"userId": "321"
},
"queryParameters": {}
}