import fs from 'fs'; import * as Axios from 'axios'; import { Method } from 'axios'; import { json } from 'express'; export interface RequestStruct { headers: Record<string, string>; body: string; url: string; method: Method; } export class HTTPParser { public static fromString(fileContent: string): RequestStruct | null { try { fileContent = fileContent.replace(/(\r\n|\n|\r)/gm, "\n"); let firstNewLineIndex = fileContent.indexOf("\n"); if (firstNewLineIndex === -1) firstNewLineIndex = fileContent.length; const startLine = fileContent.substring(0, firstNewLineIndex); const startLineArray = startLine.split(" "); const method: Method = startLineArray[0] as Method; const path = startLineArray[1]; let emptyLine = fileContent.indexOf("\n\n"); if (emptyLine === -1) emptyLine = fileContent.length; const headersArray = fileContent.substring(firstNewLineIndex + 1, emptyLine).split("\n"); const headers: Record<string, string> = {}; const body = fileContent.substring(emptyLine + 2); headersArray.forEach(h => { const delimiterIndex = h.indexOf(":"); const name = h.substring(0, delimiterIndex); const value = h.substring(delimiterIndex + 2); headers[name] = value; }); //if full url is not in the request lets assume an http to host header let url: string; if (path.startsWith("http")) url = path; else url = "http://" + (headers['host'] || headers['Host']) + path; //let axios calculate the length, since we may change it delete headers["content-length"]; delete headers["Content-Length"]; return { body: body, headers: headers, method: method, url: url }; } catch (ex) { console.error("[HTTPParser] - Error parsing request file"); console.error(ex); return null; } } public static async fromFile(filepath: string): Promise<RequestStruct | null> { return new Promise((resolve, reject) => { fs.readFile(filepath, (err, data: Buffer) => { if (err) { reject(err); return; } resolve(HTTPParser.fromString(data.toString())); }); }); } public static axiosResponseToString(r: Axios.AxiosResponse): string { let responseString = `HTTP/${r.request.res.httpVersion} ${r.status} ${r.statusText}\n`; Object.entries(r.headers).forEach(([key, value]) => { responseString += `${key}: ${value}\n`; }); const body = (typeof r.data === "object") ? JSON.stringify(r.data) : r.data; responseString += `\n${body}`; return responseString; } }