diff --git a/packages/backend/src/apps/http-request/actions/custom-request/index.ts b/packages/backend/src/apps/http-request/actions/custom-request/index.ts index 64e7a956..e386fcbb 100644 --- a/packages/backend/src/apps/http-request/actions/custom-request/index.ts +++ b/packages/backend/src/apps/http-request/actions/custom-request/index.ts @@ -10,11 +10,23 @@ type THeaderEntry = { type THeaderEntries = THeaderEntry[]; -function isPossiblyNotTextBased(contentType: string) { +function isPossiblyTextBased(contentType: string) { + if (!contentType) return false; + return contentType.startsWith('application/json') || contentType.startsWith('text/'); } +function throwIfFileSizeExceedsLimit(contentLength: string) { + const maxFileSize = 25 * 1024 * 1024; // 25MB + + if (Number(contentLength) > maxFileSize) { + throw new Error( + `Response is too large. Maximum size is 25MB. Actual size is ${contentLength}` + ); + } +} + export default defineAction({ name: 'Custom Request', key: 'customRequest', @@ -87,19 +99,32 @@ export default defineAction({ const data = $.step.parameters.data as string; const url = $.step.parameters.url as string; const headers = $.step.parameters.headers as THeaderEntries; - const maxFileSize = 25 * 1024 * 1024; // 25MB - const headersObject = headers.reduce((result, entry) => ({ ...result, [entry.key]: entry.value }), {}) + const headersObject: Record = headers.reduce((result, entry) => { + const key = entry.key?.toLowerCase(); + const value = entry.value; - const metadataResponse = await $.http.head(url, { headers: headersObject }); + if (key && value) { + return { + ...result, + [entry.key?.toLowerCase()]: entry.value + } + } - if (Number(metadataResponse.headers['content-length']) > maxFileSize) { - throw new Error( - `Response is too large. Maximum size is 25MB. Actual size is ${metadataResponse.headers['content-length']}` - ); - } + return result; + }, {}); + + let contentType = headersObject['content-type']; + + // in case HEAD request is not supported by the URL + try { + const metadataResponse = await $.http.head(url, { headers: headersObject }); + contentType = metadataResponse.headers['content-type']; + + throwIfFileSizeExceedsLimit(metadataResponse.headers['content-length']); + // eslint-disable-next-line no-empty + } catch { } - const contentType = metadataResponse.headers['content-type']; const requestData: AxiosRequestConfig = { url, method, @@ -107,15 +132,17 @@ export default defineAction({ headers: headersObject, }; - if (!isPossiblyNotTextBased(contentType)) { + if (!isPossiblyTextBased(contentType)) { requestData.responseType = 'arraybuffer'; } const response = await $.http.request(requestData); + throwIfFileSizeExceedsLimit(response.headers['content-length']); + let responseData = response.data; - if (!isPossiblyNotTextBased(contentType)) { + if (!isPossiblyTextBased(contentType)) { responseData = Buffer.from(responseData as string).toString('base64'); }