Fix issue chaining multiple requests (#3385)

* Fix issue chaining multiple requests

* refactor: use switch to prepare for leveraging exhaustiveness checking

since this will be in TypeScript soon, and this was as topical a time as any to make this change.

* fixes failing test with new behavior (and removes unused `fromResponseTag`)

* fix tests

Co-authored-by: Vincenzo De Petris <vincenzodepetris@gmail.it>
Co-authored-by: Dimitri Mitropoulos <dimitrimitropoulos@gmail.com>
Co-authored-by: Opender Singh <opender.singh@konghq.com>
This commit is contained in:
Vincenzo De Petris 2021-05-27 22:36:28 +02:00 committed by Opender Singh
parent c464e05728
commit f6504aaf89
2 changed files with 72 additions and 56 deletions

View File

@ -540,12 +540,10 @@ describe('Response tag', () => {
expect(await tag.run(context, 'raw', 'req_1', '', 'never')).toBe('Response res_existing');
});
it('does not resend recursive', async () => {
it('does not resend if request has already sent in recursive chain', async () => {
const requests = [{ _id: 'req_1', parentId: 'wrk_1' }];
const responses = [];
const context = _genTestContext(requests, responses, { fromResponseTag: true });
const context = _genTestContext(requests, responses, { requestChain: ['req_1']});
try {
await tag.run(context, 'raw', 'req_1', '', 'always');
@ -556,6 +554,16 @@ describe('Response tag', () => {
throw new Error('Running tag should have thrown exception');
});
it('does send if request has not been sent in recursive chain', async () => {
const requests = [{ _id: 'req_1', parentId: 'wrk_1' }];
const responses = [];
const context = _genTestContext(requests, responses, { requestChain: ['req_2']});
const response = await tag.run(context, 'raw', 'req_1', '', 'always');
expect(response).toBe('Response res_1')
});
});
describe('Max Age', () => {

View File

@ -121,34 +121,43 @@ module.exports.templateTags = [
let response = await context.util.models.response.getLatestForRequestId(id, environmentId);
let shouldResend = false;
if (context.context.getExtraInfo('fromResponseTag')) {
shouldResend = false;
} else if (resendBehavior === 'never') {
shouldResend = false;
} else if (resendBehavior === 'no-history') {
switch (resendBehavior) {
case 'no-history':
shouldResend = !response;
} else if (resendBehavior === 'when-expired') {
break;
case 'when-expired':
if (!response) {
shouldResend = true;
} else {
const ageSeconds = (Date.now() - response.created) / 1000;
shouldResend = ageSeconds > maxAgeSeconds;
}
} else if (resendBehavior === 'always') {
break;
case 'always':
shouldResend = true;
break;
case 'never':
default:
shouldResend = false;
break;
}
// Make sure we only send the request once per render so we don't have infinite recursion
const fromResponseTag = context.context.getExtraInfo('fromResponseTag');
if (fromResponseTag) {
const requestChain = context.context.getExtraInfo('requestChain') || [];
if (requestChain.some(id => id === request._id)) {
console.log('[response tag] Preventing recursive render');
shouldResend = false;
}
if (shouldResend && context.renderPurpose === 'send') {
console.log('[response tag] Resending dependency');
requestChain.push(request._id)
response = await context.network.sendRequest(request, [
{ name: 'fromResponseTag', value: true },
{ name: 'requestChain', value: requestChain }
]);
}
@ -172,16 +181,17 @@ module.exports.templateTags = [
}
const sanitizedFilter = filter.trim();
if (field === 'header') {
return matchHeader(response.headers, sanitizedFilter);
} else if (field === 'url') {
return response.url;
} else if (field === 'raw') {
const bodyBuffer = context.util.models.response.getBodyBuffer(response, '');
const match = response.contentType.match(/charset=([\w-]+)/);
const match = response.contentType && response.contentType.match(/charset=([\w-]+)/);
const charset = match && match.length >= 2 ? match[1] : 'utf-8';
switch (field) {
case 'header':
return matchHeader(response.headers, sanitizedFilter);
case 'url':
return response.url;
case 'raw':
// Sometimes iconv conversion fails so fallback to regular buffer
try {
return iconv.decode(bodyBuffer, charset);
@ -189,11 +199,8 @@ module.exports.templateTags = [
console.warn('[response] Failed to decode body', err);
return bodyBuffer.toString();
}
} else if (field === 'body') {
const bodyBuffer = context.util.models.response.getBodyBuffer(response, '');
const match = response.contentType.match(/charset=([\w-]+)/);
const charset = match && match.length >= 2 ? match[1] : 'utf-8';
case 'body':
// Sometimes iconv conversion fails so fallback to regular buffer
let body;
try {
@ -208,7 +215,8 @@ module.exports.templateTags = [
} else {
return matchXPath(body, sanitizedFilter);
}
} else {
default:
throw new Error(`Unknown field ${field}`);
}
},