Skip to content

Commit

Permalink
Save actual request files natively
Browse files Browse the repository at this point in the history
  • Loading branch information
skirankumars31 committed Jun 13, 2024
1 parent d70d16c commit 9255e73
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 5 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ node_modules
*.vsix
*.env
.eslintcache
.idea
1 change: 1 addition & 0 deletions src/plugins/core/parse/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * from './commentHttpRegionParser';
export * from './metaHttpRegionParser';
export * from './multipartMixedInterceptor';
export * from './outputRedirectionHttpRegionParser';
export * from './inputRedirectionHttpRegionParser';
export * from './requestBodyHttpRegionParser';
export * from './requestHttpRegionParser';
export * from './responseHttpRegionParser';
Expand Down
116 changes: 116 additions & 0 deletions src/plugins/core/parse/inputRedirectionHttpRegionParser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { fileProvider, log } from '../../../io';
import * as models from '../../../models';
import * as utils from '../../../utils';
import { transformToBufferOrString } from '../request';

export async function parseInputRedirection(
getLineReader: models.getHttpLineGenerator,
context: models.ParserContext
): Promise<models.HttpRegionParserResult> {
if (context.httpRegion.request) {
const lineReader = getLineReader();

const next = lineReader.next();
if (!next.done) {
const textLine = next.value.textLine;

console.log(`file Calling input redirection parser${textLine}`);

const match = /^<(?:(?<injectVariables>@)(?<encoding>\w+)?)?\s+(?<fileName>.+?)\s*$/u.exec(textLine);

if (match && match.groups?.fileName) {
console.log(match.groups.fileName.trim());
const fileName = `redirect-actual-${match.groups.fileName.trim()}`;
const force: boolean = true;

context.httpRegion.hooks.onRequest.addHook('inputRedirection', async (request, context) => {
try {
console.log(`file request body is ${request.body}`);
if (request.body) {
console.log('file Request body is present');
const body = await transformToBufferOrString(request.body, context);
const fileNameReplaced = utils.toString(
await utils.replaceVariables(fileName, models.VariableType.variable, context)
);
console.log(`File name replaced is ${fileNameReplaced}`);

if (fileNameReplaced) {
const file = await getInputRedirectionFileName(fileNameReplaced, force, context.httpFile.fileName);
console.log(`File name is ${file}`);
if (file) {
if (typeof body === 'string') {
await fileProvider.writeBuffer(file, Buffer.from(body));
} else {
await fileProvider.writeBuffer(file, body);
}
} else {
log.debug(`file ${fileName} not found`);
}
} else {
log.debug(`file ${fileName} not found`);
}
}
} catch (err) {
log.error(`input redirection failed for ${fileName}`, err);
}
});
return {
nextParserLine: next.value.line,
symbols: [
new models.HttpSymbol({
name: match.groups.key,
description: match.groups.value,
kind: models.HttpSymbolKind.response,
startLine: next.value.line,
startOffset: 0,
endLine: next.value.line,
endOffset: next.value.textLine.length,
children: [
new models.HttpSymbol({
name: 'filename',
description: fileName,
kind: models.HttpSymbolKind.path,
startLine: next.value.line,
startOffset: next.value.textLine.indexOf(fileName),
endLine: next.value.line,
endOffset: next.value.textLine.indexOf(fileName) + fileName.length,
}),
],
}),
],
};
}
}
}
return false;
}

async function getInputRedirectionFileName(fileName: string, force: boolean, baseName: models.PathLike) {
let file = await toAbsoluteFileName(fileName, baseName);

if (!force) {
if (await fileProvider.exists(file)) {
const dotIndex = fileName.lastIndexOf('.');
if (dotIndex > 0 && dotIndex < fileName.length - 2) {
const path = fileName.slice(0, dotIndex);
const extension = fileName.slice(dotIndex + 1);
let index = 1;

file = await toAbsoluteFileName(`${path}-${index}.${extension}`, baseName);
while (await fileProvider.exists(file)) {
file = await toAbsoluteFileName(`${path}-${index++}.${extension}`, baseName);
}
}
}
}
return file;
}
async function toAbsoluteFileName(fileName: string, baseName: models.PathLike) {
if (!(await fileProvider.isAbsolute(fileName))) {
const dirName = fileProvider.dirname(baseName);
if (dirName) {
return fileProvider.joinPath(dirName, fileName);
}
}
return fileName;
}
82 changes: 80 additions & 2 deletions src/plugins/core/parse/requestBodyHttpRegionParser.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import * as models from '../../../models';
import * as utils from '../../../utils';
import { fileProvider, log } from '../../../io';
import { transformToBufferOrString } from '../request';

export async function parseRequestBody(
getLineReader: models.getHttpLineGenerator,
Expand All @@ -10,8 +12,16 @@ export async function parseRequestBody(
if (context.httpRegion.request) {
const requestBody = getRequestBody(context);
const next = lineReader.next();

if (!next.done) {
if (requestBody.rawBody.length > 0 || !utils.isStringEmpty(next.value.textLine)) {
const textLine = next.value.textLine;

const match =
/^<(?:(?<injectVariables>@)(?<encoding>\w+)?)?\s+(?<fileName>.+?)\s+>>(?<force>!)?\s+(?<outputFile>.+?)\s*$/u.exec(
textLine
);

if (requestBody.rawBody.length > 0 || !utils.isStringEmpty(textLine)) {
const symbols: Array<models.HttpSymbol> = [];

if (!requestBody.symbol || requestBody.symbol.endLine !== next.value.line - 1) {
Expand All @@ -23,7 +33,7 @@ export async function parseRequestBody(
startOffset: 0,
endLine: next.value.line,
endOffset: next.value.textLine.length,
children: utils.parseHandlebarsSymbols(next.value.textLine, next.value.line),
children: utils.parseHandlebarsSymbols(textLine, next.value.line),
});
symbols.push(requestBody.symbol);
} else {
Expand All @@ -32,6 +42,44 @@ export async function parseRequestBody(
requestBody.symbol.children?.push?.(...utils.parseHandlebarsSymbols(next.value.textLine, next.value.line));
}

if (match && match.groups?.outputFile) {
console.log(match.groups.outputFile.trim());
const fileName = match.groups.outputFile.trim();
const force: boolean = !!match.groups.force;

context.httpRegion.hooks.onRequest.addHook('inputRedirection', async (request, context) => {
try {
console.log(`request body is ${request.body}`);
if (request.body) {
console.log('Request body is present');
const body = await transformToBufferOrString(request.body, context);
const fileNameReplaced = utils.toString(
await utils.replaceVariables(fileName, models.VariableType.variable, context)
);
console.log(`File name replaced is ${fileNameReplaced}`);

if (fileNameReplaced) {
const file = await getInputRedirectionFileName(fileNameReplaced, force, context.httpFile.fileName);
console.log(`File name is ${file}`);
if (file) {
if (typeof body === 'string') {
await fileProvider.writeBuffer(file, Buffer.from(body));
} else {
await fileProvider.writeBuffer(file, body);
}
} else {
log.debug(`file ${fileName} not found`);
}
} else {
log.debug(`file ${fileName} not found`);
}
}
} catch (err) {
log.error(`input redirection failed for ${fileName}`, err);
}
});
}

const fileImport = utils.parseFileImport(next.value.textLine);
if (fileImport) {
requestBody.rawBody.push(fileImport);
Expand Down Expand Up @@ -70,3 +118,33 @@ export function getRequestBody(context: models.ParserContext) {
}
return result;
}

async function getInputRedirectionFileName(fileName: string, force: boolean, baseName: models.PathLike) {
let file = await toAbsoluteFileName(fileName, baseName);

if (!force) {
if (await fileProvider.exists(file)) {
const dotIndex = fileName.lastIndexOf('.');
if (dotIndex > 0 && dotIndex < fileName.length - 2) {
const path = fileName.slice(0, dotIndex);
const extension = fileName.slice(dotIndex + 1);
let index = 1;

file = await toAbsoluteFileName(`${path}-${index}.${extension}`, baseName);
while (await fileProvider.exists(file)) {
file = await toAbsoluteFileName(`${path}-${index++}.${extension}`, baseName);
}
}
}
}
return file;
}
async function toAbsoluteFileName(fileName: string, baseName: models.PathLike) {
if (!(await fileProvider.isAbsolute(fileName))) {
const dirName = fileProvider.dirname(baseName);
if (dirName) {
return fileProvider.joinPath(dirName, fileName);
}
}
return fileName;
}
1 change: 0 additions & 1 deletion src/plugins/core/registerCorePlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ function initParseHook(api: models.HttpyacHooksApi) {
api.hooks.parse.addHook('responseRef', parse.parseResponseRef);
api.hooks.parse.addHook('response', parse.parseResponse);
api.hooks.parse.addHook('requestBody', parse.parseRequestBody);

api.hooks.parse.addInterceptor(new parse.MultipartMixedInterceptor());
}
function initParseEndHook(api: models.HttpyacHooksApi) {
Expand Down
7 changes: 5 additions & 2 deletions src/utils/parserUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,8 +542,11 @@ export async function parseInlineResponse(
}

export function parseFileImport(text: string) {
const fileImport = /^<(?:(?<injectVariables>@)(?<encoding>\w+)?)?\s+(?<fileName>.+?)\s*$/u.exec(text);
if (fileImport && fileImport.length === 4 && fileImport.groups) {
const fileImport =
/^<(?:(?<injectVariables>@)(?<encoding>\w+)?)?\s+(?<fileName>.+?)\s+>>(?<force>!)?\s+(?<outputFile>.+?)\s*$/u.exec(
text
);
if (fileImport && fileImport.length === 6 && fileImport.groups) {
return {
fileName: fileImport.groups.fileName.trim(),
injectVariables: !!fileImport.groups.injectVariables,
Expand Down

0 comments on commit 9255e73

Please sign in to comment.