diff --git a/src/models/requestParserFactory.ts b/src/models/requestParserFactory.ts index ec730ee6..ad4fe0e7 100644 --- a/src/models/requestParserFactory.ts +++ b/src/models/requestParserFactory.ts @@ -1,4 +1,5 @@ import { CurlRequestParser } from '../utils/curlRequestParser'; +import { FetchRequestParser } from '../utils/fetchRequestParser'; import { HttpRequestParser } from '../utils/httpRequestParser'; import { IRestClientSettings, SystemSettings } from './configurationSettings'; import { RequestParser } from './requestParser'; @@ -6,6 +7,7 @@ import { RequestParser } from './requestParser'; export class RequestParserFactory { private static readonly curlRegex: RegExp = /^\s*curl/i; + private static readonly fetchRegex: RegExp = /^\s*fetch\s*\(/i; public static createRequestParser(rawRequest: string): RequestParser; public static createRequestParser(rawRequest: string, settings: IRestClientSettings): RequestParser; @@ -13,6 +15,8 @@ export class RequestParserFactory { settings = settings || SystemSettings.Instance; if (RequestParserFactory.curlRegex.test(rawHttpRequest)) { return new CurlRequestParser(rawHttpRequest, settings); + } else if (RequestParserFactory.fetchRegex.test(rawHttpRequest)) { + return new FetchRequestParser(rawHttpRequest, settings); } else { return new HttpRequestParser(rawHttpRequest, settings); } diff --git a/src/utils/fetchRequestParser.ts b/src/utils/fetchRequestParser.ts new file mode 100644 index 00000000..acdda3d9 --- /dev/null +++ b/src/utils/fetchRequestParser.ts @@ -0,0 +1,56 @@ +import { RequestHeaders } from '../models/base'; +import { IRestClientSettings } from '../models/configurationSettings'; +import { HttpRequest } from '../models/httpRequest'; +import { RequestParser } from '../models/requestParser'; +import { hasHeader } from './misc'; + +const DefaultContentType: string = 'application/json'; + +export class FetchRequestParser implements RequestParser { + + private readonly fetchRegex: RegExp = /^\s*fetch\s*\(\s*(?:'([^']+)'|"([^"]+)"|`([^`]+)`)\s*(?:,\s*(\{[\s\S]*\}))?\s*\)\s*;?\s*$/i; + + public constructor(private readonly requestRawText: string, private readonly settings: IRestClientSettings) { + } + + public async parseHttpRequest(name?: string): Promise { + const match = this.fetchRegex.exec(this.requestRawText); + if (!match) { + throw new Error('Invalid fetch request format.'); + } + + const url = match[1] || match[2] || match[3]; + const optionsStr = match[4]; + + let options: any = {}; + if (optionsStr) { + try { + options = new Function(`return ${optionsStr}`)(); + } catch (error) { + // Ignore parse error and keep options as empty + } + } + + const method = (options.method || 'GET').toUpperCase(); + + const headers: RequestHeaders = { ...this.settings.defaultHeaders }; + if (options.headers) { + for (const [key, value] of Object.entries(options.headers)) { + headers[key] = value as string; + } + } + + let body = options.body; + if (body === null || body === undefined) { + body = undefined; + } else if (typeof body !== 'string') { + body = JSON.stringify(body); + } + + if (body && !hasHeader(headers, 'content-type')) { + headers['Content-Type'] = DefaultContentType; + } + + return new HttpRequest(method, url, headers, body, body, name); + } +}