import defineAction from '../../../../helpers/define-action.js'; function isPossiblyTextBased(contentType) { if (!contentType) return false; return ( contentType.startsWith('application/json') || contentType.startsWith('text/') ); } function throwIfFileSizeExceedsLimit(contentLength) { 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', description: 'Makes a custom HTTP request by providing raw details.', arguments: [ { label: 'Method', key: 'method', type: 'dropdown', required: true, description: `The HTTP method we'll use to perform the request.`, value: 'GET', options: [ { label: 'DELETE', value: 'DELETE' }, { label: 'GET', value: 'GET' }, { label: 'PATCH', value: 'PATCH' }, { label: 'POST', value: 'POST' }, { label: 'PUT', value: 'PUT' }, ], }, { label: 'URL', key: 'url', type: 'string', required: true, description: 'Any URL with a querystring will be re-encoded properly.', variables: true, }, { label: 'Data', key: 'data', type: 'string', required: false, description: 'Place raw JSON data here.', variables: true, }, { label: 'Headers', key: 'headers', type: 'dynamic', required: false, description: 'Add or remove headers as needed', value: [ { key: 'Content-Type', value: 'application/json', }, ], fields: [ { label: 'Key', key: 'key', type: 'string', required: true, description: 'Header key', variables: true, }, { label: 'Value', key: 'value', type: 'string', required: true, description: 'Header value', variables: true, }, ], }, ], async run($) { const method = $.step.parameters.method; const data = $.step.parameters.data; const url = $.step.parameters.url; const headers = $.step.parameters.headers; const headersObject = headers.reduce((result, entry) => { const key = entry.key?.toLowerCase(); const value = entry.value; if (key && value) { return { ...result, [entry.key?.toLowerCase()]: entry.value, }; } 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 requestData = { url, method, data, headers: headersObject, }; if (!isPossiblyTextBased(contentType)) { requestData.responseType = 'arraybuffer'; } const response = await $.http.request(requestData); throwIfFileSizeExceedsLimit(response.headers['content-length']); let responseData = response.data; if (!isPossiblyTextBased(contentType)) { responseData = Buffer.from(responseData).toString('base64'); } $.setActionItem({ raw: { data: responseData } }); }, });