budibase/packages/server/src/integrations/rest.ts

496 lines
13 KiB
TypeScript
Raw Normal View History

2021-06-24 19:17:26 +02:00
import {
2024-08-01 18:57:33 +02:00
BodyType,
DatasourceFieldType,
2024-05-17 15:16:08 +02:00
HttpMethod,
Integration,
IntegrationBase,
2024-05-17 15:16:08 +02:00
PaginationConfig,
PaginationValues,
2024-05-17 15:16:08 +02:00
QueryType,
RestAuthType,
RestBasicAuthConfig,
RestBearerAuthConfig,
2024-05-17 15:16:08 +02:00
RestConfig,
RestQueryFields as RestQuery,
} from "@budibase/types"
2023-07-27 21:36:32 +02:00
import get from "lodash/get"
2022-09-09 23:14:28 +02:00
import * as https from "https"
2022-09-09 18:18:19 +02:00
import qs from "querystring"
2024-08-01 18:57:33 +02:00
import type { Response, RequestInit } from "node-fetch"
2024-05-17 15:16:08 +02:00
import fetch from "node-fetch"
import { formatBytes } from "../utilities"
import { performance } from "perf_hooks"
import FormData from "form-data"
import { URLSearchParams } from "url"
import { blacklist } from "@budibase/backend-core"
REST file handling and SMTP automation block attachments (#13403) * handle files in rest connector * fetch presigned url and return * further updates to handle files in rest connector * remove unused important and fix extension bug * wrong expiry param * tests * add const for temp bucket * handle ttl on bucket * more bucket ttl work * split out fileresponse and xmlresponse into utils * lint * remove log * fix tests * some pr comments * update function naming and lint * adding back needed response for frontend * use fsp * handle different content-disposition and potential path traversal * add test container for s3 / minio * add test case for filename* and ascii filenames * move tests into separate describe * remove log * up timeout * switch to minio image instead of localstack * use minio image instead of s3 for testing * stream file upload instead * use streamUpload and update signatures * update bucketcreate return * throw real error * tidy up * pro * pro ref fix? * pro fix * pro fix? * move minio test provider to backend-core * update email builder to allow attachments * testing for sending files via smtp * use backend-core minio test container in server * handle different types of url * fix minio test provider * test with container host * lint * try different hostname? * Revert "try different hostname?" This reverts commit cfefdb8ded2b49462604053cf140e7292771c651. * fix issue with fetching of signed url with test minio * update autoamtion attachments to take filename and url * fix tests * pro ref * fix parsing of url object * pr comments and linting * pro ref * fix pro again * fix pro * account-portal * fix null issue * fix ref * ref * When sending a file attachment in email fetch it directly from our object store * add more checks to ensure we're working with a signed url * update test to account for direct object store read * formatting * fix time issues within test * update bucket and path extraction to regex * use const in regex * pro * Updating TTL handling in upload functions (#13539) * Updating TTL handling in upload functions * describe ttl type * account for ttl creation in existing buckets and update types * fix tests * pro * pro
2024-04-22 17:30:57 +02:00
import { handleFileResponse, handleXml } from "./utils"
import { parse } from "content-disposition"
import path from "path"
import { Builder as XmlBuilder } from "xml2js"
import { getAttachmentHeaders } from "./utils/restUtils"
2021-12-02 18:53:14 +01:00
const coreFields = {
path: {
type: DatasourceFieldType.STRING,
2021-12-02 18:53:14 +01:00
display: "URL",
},
queryString: {
type: DatasourceFieldType.STRING,
2021-12-02 18:53:14 +01:00
},
headers: {
type: DatasourceFieldType.OBJECT,
2021-12-02 18:53:14 +01:00
},
enabledHeaders: {
type: DatasourceFieldType.OBJECT,
2021-12-02 18:53:14 +01:00
},
requestBody: {
type: DatasourceFieldType.JSON,
2021-12-02 18:53:14 +01:00
},
bodyType: {
type: DatasourceFieldType.STRING,
enum: Object.values(BodyType),
2021-12-02 18:53:14 +01:00
},
pagination: {
type: DatasourceFieldType.OBJECT,
},
2021-12-02 18:53:14 +01:00
}
const SCHEMA: Integration = {
docs: "https://github.com/node-fetch/node-fetch",
description:
"With the REST API datasource, you can connect, query and pull data from multiple REST APIs. You can then use the retrieved data to build apps.",
friendlyName: "REST API",
type: "API",
datasource: {
url: {
type: DatasourceFieldType.STRING,
default: "",
required: false,
deprecated: true,
},
defaultHeaders: {
type: DatasourceFieldType.OBJECT,
required: false,
default: {},
},
2022-09-10 01:25:35 +02:00
rejectUnauthorized: {
display: "Reject Unauthorized",
2022-09-10 01:25:35 +02:00
type: DatasourceFieldType.BOOLEAN,
default: true,
required: false,
},
2024-05-17 15:16:08 +02:00
downloadImages: {
display: "Download images",
type: DatasourceFieldType.BOOLEAN,
default: true,
required: false,
},
},
query: {
create: {
readable: true,
displayName: HttpMethod.POST,
type: QueryType.FIELDS,
fields: coreFields,
},
read: {
displayName: HttpMethod.GET,
readable: true,
type: QueryType.FIELDS,
fields: coreFields,
},
update: {
displayName: HttpMethod.PUT,
readable: true,
type: QueryType.FIELDS,
fields: coreFields,
},
patch: {
displayName: HttpMethod.PATCH,
readable: true,
type: QueryType.FIELDS,
fields: coreFields,
},
delete: {
displayName: HttpMethod.DELETE,
type: QueryType.FIELDS,
fields: coreFields,
},
},
}
2024-08-01 18:57:33 +02:00
interface ParsedResponse {
data: any
info: {
code: number
size: string
time: string
}
extra?: {
raw: string | undefined
headers: Record<string, string[] | string>
}
pagination?: {
cursor: any
}
}
export class RestIntegration implements IntegrationBase {
private config: RestConfig
private headers: {
[key: string]: string
} = {}
private startTimeMs: number = performance.now()
constructor(config: RestConfig) {
this.config = config
}
2024-08-01 18:57:33 +02:00
async parseResponse(
response: Response,
pagination?: PaginationConfig
): Promise<ParsedResponse> {
let data: any[] | string | undefined,
raw: string | undefined,
headers: Record<string, string[] | string> = {},
filename: string | undefined
REST file handling and SMTP automation block attachments (#13403) * handle files in rest connector * fetch presigned url and return * further updates to handle files in rest connector * remove unused important and fix extension bug * wrong expiry param * tests * add const for temp bucket * handle ttl on bucket * more bucket ttl work * split out fileresponse and xmlresponse into utils * lint * remove log * fix tests * some pr comments * update function naming and lint * adding back needed response for frontend * use fsp * handle different content-disposition and potential path traversal * add test container for s3 / minio * add test case for filename* and ascii filenames * move tests into separate describe * remove log * up timeout * switch to minio image instead of localstack * use minio image instead of s3 for testing * stream file upload instead * use streamUpload and update signatures * update bucketcreate return * throw real error * tidy up * pro * pro ref fix? * pro fix * pro fix? * move minio test provider to backend-core * update email builder to allow attachments * testing for sending files via smtp * use backend-core minio test container in server * handle different types of url * fix minio test provider * test with container host * lint * try different hostname? * Revert "try different hostname?" This reverts commit cfefdb8ded2b49462604053cf140e7292771c651. * fix issue with fetching of signed url with test minio * update autoamtion attachments to take filename and url * fix tests * pro ref * fix parsing of url object * pr comments and linting * pro ref * fix pro again * fix pro * account-portal * fix null issue * fix ref * ref * When sending a file attachment in email fetch it directly from our object store * add more checks to ensure we're working with a signed url * update test to account for direct object store read * formatting * fix time issues within test * update bucket and path extraction to regex * use const in regex * pro * Updating TTL handling in upload functions (#13539) * Updating TTL handling in upload functions * describe ttl type * account for ttl creation in existing buckets and update types * fix tests * pro * pro
2024-04-22 17:30:57 +02:00
const { contentType, contentDisposition } = getAttachmentHeaders(
2024-05-17 15:16:08 +02:00
response.headers,
{ downloadImages: this.config.downloadImages }
)
let contentLength = response.headers.get("content-length")
let isSuccess = response.status >= 200 && response.status < 300
REST file handling and SMTP automation block attachments (#13403) * handle files in rest connector * fetch presigned url and return * further updates to handle files in rest connector * remove unused important and fix extension bug * wrong expiry param * tests * add const for temp bucket * handle ttl on bucket * more bucket ttl work * split out fileresponse and xmlresponse into utils * lint * remove log * fix tests * some pr comments * update function naming and lint * adding back needed response for frontend * use fsp * handle different content-disposition and potential path traversal * add test container for s3 / minio * add test case for filename* and ascii filenames * move tests into separate describe * remove log * up timeout * switch to minio image instead of localstack * use minio image instead of s3 for testing * stream file upload instead * use streamUpload and update signatures * update bucketcreate return * throw real error * tidy up * pro * pro ref fix? * pro fix * pro fix? * move minio test provider to backend-core * update email builder to allow attachments * testing for sending files via smtp * use backend-core minio test container in server * handle different types of url * fix minio test provider * test with container host * lint * try different hostname? * Revert "try different hostname?" This reverts commit cfefdb8ded2b49462604053cf140e7292771c651. * fix issue with fetching of signed url with test minio * update autoamtion attachments to take filename and url * fix tests * pro ref * fix parsing of url object * pr comments and linting * pro ref * fix pro again * fix pro * account-portal * fix null issue * fix ref * ref * When sending a file attachment in email fetch it directly from our object store * add more checks to ensure we're working with a signed url * update test to account for direct object store read * formatting * fix time issues within test * update bucket and path extraction to regex * use const in regex * pro * Updating TTL handling in upload functions (#13539) * Updating TTL handling in upload functions * describe ttl type * account for ttl creation in existing buckets and update types * fix tests * pro * pro
2024-04-22 17:30:57 +02:00
if (
(contentDisposition.includes("filename") ||
contentDisposition.includes("attachment") ||
contentDisposition.includes("form-data")) &&
isSuccess
REST file handling and SMTP automation block attachments (#13403) * handle files in rest connector * fetch presigned url and return * further updates to handle files in rest connector * remove unused important and fix extension bug * wrong expiry param * tests * add const for temp bucket * handle ttl on bucket * more bucket ttl work * split out fileresponse and xmlresponse into utils * lint * remove log * fix tests * some pr comments * update function naming and lint * adding back needed response for frontend * use fsp * handle different content-disposition and potential path traversal * add test container for s3 / minio * add test case for filename* and ascii filenames * move tests into separate describe * remove log * up timeout * switch to minio image instead of localstack * use minio image instead of s3 for testing * stream file upload instead * use streamUpload and update signatures * update bucketcreate return * throw real error * tidy up * pro * pro ref fix? * pro fix * pro fix? * move minio test provider to backend-core * update email builder to allow attachments * testing for sending files via smtp * use backend-core minio test container in server * handle different types of url * fix minio test provider * test with container host * lint * try different hostname? * Revert "try different hostname?" This reverts commit cfefdb8ded2b49462604053cf140e7292771c651. * fix issue with fetching of signed url with test minio * update autoamtion attachments to take filename and url * fix tests * pro ref * fix parsing of url object * pr comments and linting * pro ref * fix pro again * fix pro * account-portal * fix null issue * fix ref * ref * When sending a file attachment in email fetch it directly from our object store * add more checks to ensure we're working with a signed url * update test to account for direct object store read * formatting * fix time issues within test * update bucket and path extraction to regex * use const in regex * pro * Updating TTL handling in upload functions (#13539) * Updating TTL handling in upload functions * describe ttl type * account for ttl creation in existing buckets and update types * fix tests * pro * pro
2024-04-22 17:30:57 +02:00
) {
filename =
path.basename(parse(contentDisposition).parameters?.filename) || ""
}
let triedParsing: boolean = false,
responseTxt: string | undefined
try {
REST file handling and SMTP automation block attachments (#13403) * handle files in rest connector * fetch presigned url and return * further updates to handle files in rest connector * remove unused important and fix extension bug * wrong expiry param * tests * add const for temp bucket * handle ttl on bucket * more bucket ttl work * split out fileresponse and xmlresponse into utils * lint * remove log * fix tests * some pr comments * update function naming and lint * adding back needed response for frontend * use fsp * handle different content-disposition and potential path traversal * add test container for s3 / minio * add test case for filename* and ascii filenames * move tests into separate describe * remove log * up timeout * switch to minio image instead of localstack * use minio image instead of s3 for testing * stream file upload instead * use streamUpload and update signatures * update bucketcreate return * throw real error * tidy up * pro * pro ref fix? * pro fix * pro fix? * move minio test provider to backend-core * update email builder to allow attachments * testing for sending files via smtp * use backend-core minio test container in server * handle different types of url * fix minio test provider * test with container host * lint * try different hostname? * Revert "try different hostname?" This reverts commit cfefdb8ded2b49462604053cf140e7292771c651. * fix issue with fetching of signed url with test minio * update autoamtion attachments to take filename and url * fix tests * pro ref * fix parsing of url object * pr comments and linting * pro ref * fix pro again * fix pro * account-portal * fix null issue * fix ref * ref * When sending a file attachment in email fetch it directly from our object store * add more checks to ensure we're working with a signed url * update test to account for direct object store read * formatting * fix time issues within test * update bucket and path extraction to regex * use const in regex * pro * Updating TTL handling in upload functions (#13539) * Updating TTL handling in upload functions * describe ttl type * account for ttl creation in existing buckets and update types * fix tests * pro * pro
2024-04-22 17:30:57 +02:00
if (filename) {
return handleFileResponse(response, filename, this.startTimeMs)
2023-04-03 16:36:34 +02:00
} else {
2024-05-24 13:40:58 +02:00
responseTxt = response.text ? await response.text() : ""
if (!contentLength && responseTxt) {
contentLength = Buffer.byteLength(responseTxt, "utf8").toString()
}
2024-05-24 13:40:58 +02:00
const hasContent =
(contentLength && parseInt(contentLength) > 0) ||
responseTxt.length > 0
REST file handling and SMTP automation block attachments (#13403) * handle files in rest connector * fetch presigned url and return * further updates to handle files in rest connector * remove unused important and fix extension bug * wrong expiry param * tests * add const for temp bucket * handle ttl on bucket * more bucket ttl work * split out fileresponse and xmlresponse into utils * lint * remove log * fix tests * some pr comments * update function naming and lint * adding back needed response for frontend * use fsp * handle different content-disposition and potential path traversal * add test container for s3 / minio * add test case for filename* and ascii filenames * move tests into separate describe * remove log * up timeout * switch to minio image instead of localstack * use minio image instead of s3 for testing * stream file upload instead * use streamUpload and update signatures * update bucketcreate return * throw real error * tidy up * pro * pro ref fix? * pro fix * pro fix? * move minio test provider to backend-core * update email builder to allow attachments * testing for sending files via smtp * use backend-core minio test container in server * handle different types of url * fix minio test provider * test with container host * lint * try different hostname? * Revert "try different hostname?" This reverts commit cfefdb8ded2b49462604053cf140e7292771c651. * fix issue with fetching of signed url with test minio * update autoamtion attachments to take filename and url * fix tests * pro ref * fix parsing of url object * pr comments and linting * pro ref * fix pro again * fix pro * account-portal * fix null issue * fix ref * ref * When sending a file attachment in email fetch it directly from our object store * add more checks to ensure we're working with a signed url * update test to account for direct object store read * formatting * fix time issues within test * update bucket and path extraction to regex * use const in regex * pro * Updating TTL handling in upload functions (#13539) * Updating TTL handling in upload functions * describe ttl type * account for ttl creation in existing buckets and update types * fix tests * pro * pro
2024-04-22 17:30:57 +02:00
if (response.status === 204) {
data = []
raw = ""
} else if (hasContent && contentType.includes("application/json")) {
triedParsing = true
data = JSON.parse(responseTxt)
raw = responseTxt
REST file handling and SMTP automation block attachments (#13403) * handle files in rest connector * fetch presigned url and return * further updates to handle files in rest connector * remove unused important and fix extension bug * wrong expiry param * tests * add const for temp bucket * handle ttl on bucket * more bucket ttl work * split out fileresponse and xmlresponse into utils * lint * remove log * fix tests * some pr comments * update function naming and lint * adding back needed response for frontend * use fsp * handle different content-disposition and potential path traversal * add test container for s3 / minio * add test case for filename* and ascii filenames * move tests into separate describe * remove log * up timeout * switch to minio image instead of localstack * use minio image instead of s3 for testing * stream file upload instead * use streamUpload and update signatures * update bucketcreate return * throw real error * tidy up * pro * pro ref fix? * pro fix * pro fix? * move minio test provider to backend-core * update email builder to allow attachments * testing for sending files via smtp * use backend-core minio test container in server * handle different types of url * fix minio test provider * test with container host * lint * try different hostname? * Revert "try different hostname?" This reverts commit cfefdb8ded2b49462604053cf140e7292771c651. * fix issue with fetching of signed url with test minio * update autoamtion attachments to take filename and url * fix tests * pro ref * fix parsing of url object * pr comments and linting * pro ref * fix pro again * fix pro * account-portal * fix null issue * fix ref * ref * When sending a file attachment in email fetch it directly from our object store * add more checks to ensure we're working with a signed url * update test to account for direct object store read * formatting * fix time issues within test * update bucket and path extraction to regex * use const in regex * pro * Updating TTL handling in upload functions (#13539) * Updating TTL handling in upload functions * describe ttl type * account for ttl creation in existing buckets and update types * fix tests * pro * pro
2024-04-22 17:30:57 +02:00
} else if (
(hasContent && contentType.includes("text/xml")) ||
REST file handling and SMTP automation block attachments (#13403) * handle files in rest connector * fetch presigned url and return * further updates to handle files in rest connector * remove unused important and fix extension bug * wrong expiry param * tests * add const for temp bucket * handle ttl on bucket * more bucket ttl work * split out fileresponse and xmlresponse into utils * lint * remove log * fix tests * some pr comments * update function naming and lint * adding back needed response for frontend * use fsp * handle different content-disposition and potential path traversal * add test container for s3 / minio * add test case for filename* and ascii filenames * move tests into separate describe * remove log * up timeout * switch to minio image instead of localstack * use minio image instead of s3 for testing * stream file upload instead * use streamUpload and update signatures * update bucketcreate return * throw real error * tidy up * pro * pro ref fix? * pro fix * pro fix? * move minio test provider to backend-core * update email builder to allow attachments * testing for sending files via smtp * use backend-core minio test container in server * handle different types of url * fix minio test provider * test with container host * lint * try different hostname? * Revert "try different hostname?" This reverts commit cfefdb8ded2b49462604053cf140e7292771c651. * fix issue with fetching of signed url with test minio * update autoamtion attachments to take filename and url * fix tests * pro ref * fix parsing of url object * pr comments and linting * pro ref * fix pro again * fix pro * account-portal * fix null issue * fix ref * ref * When sending a file attachment in email fetch it directly from our object store * add more checks to ensure we're working with a signed url * update test to account for direct object store read * formatting * fix time issues within test * update bucket and path extraction to regex * use const in regex * pro * Updating TTL handling in upload functions (#13539) * Updating TTL handling in upload functions * describe ttl type * account for ttl creation in existing buckets and update types * fix tests * pro * pro
2024-04-22 17:30:57 +02:00
contentType.includes("application/xml")
) {
triedParsing = true
let xmlResponse = await handleXml(responseTxt)
REST file handling and SMTP automation block attachments (#13403) * handle files in rest connector * fetch presigned url and return * further updates to handle files in rest connector * remove unused important and fix extension bug * wrong expiry param * tests * add const for temp bucket * handle ttl on bucket * more bucket ttl work * split out fileresponse and xmlresponse into utils * lint * remove log * fix tests * some pr comments * update function naming and lint * adding back needed response for frontend * use fsp * handle different content-disposition and potential path traversal * add test container for s3 / minio * add test case for filename* and ascii filenames * move tests into separate describe * remove log * up timeout * switch to minio image instead of localstack * use minio image instead of s3 for testing * stream file upload instead * use streamUpload and update signatures * update bucketcreate return * throw real error * tidy up * pro * pro ref fix? * pro fix * pro fix? * move minio test provider to backend-core * update email builder to allow attachments * testing for sending files via smtp * use backend-core minio test container in server * handle different types of url * fix minio test provider * test with container host * lint * try different hostname? * Revert "try different hostname?" This reverts commit cfefdb8ded2b49462604053cf140e7292771c651. * fix issue with fetching of signed url with test minio * update autoamtion attachments to take filename and url * fix tests * pro ref * fix parsing of url object * pr comments and linting * pro ref * fix pro again * fix pro * account-portal * fix null issue * fix ref * ref * When sending a file attachment in email fetch it directly from our object store * add more checks to ensure we're working with a signed url * update test to account for direct object store read * formatting * fix time issues within test * update bucket and path extraction to regex * use const in regex * pro * Updating TTL handling in upload functions (#13539) * Updating TTL handling in upload functions * describe ttl type * account for ttl creation in existing buckets and update types * fix tests * pro * pro
2024-04-22 17:30:57 +02:00
data = xmlResponse.data
raw = xmlResponse.rawXml
} else {
data = responseTxt
raw = data as string
REST file handling and SMTP automation block attachments (#13403) * handle files in rest connector * fetch presigned url and return * further updates to handle files in rest connector * remove unused important and fix extension bug * wrong expiry param * tests * add const for temp bucket * handle ttl on bucket * more bucket ttl work * split out fileresponse and xmlresponse into utils * lint * remove log * fix tests * some pr comments * update function naming and lint * adding back needed response for frontend * use fsp * handle different content-disposition and potential path traversal * add test container for s3 / minio * add test case for filename* and ascii filenames * move tests into separate describe * remove log * up timeout * switch to minio image instead of localstack * use minio image instead of s3 for testing * stream file upload instead * use streamUpload and update signatures * update bucketcreate return * throw real error * tidy up * pro * pro ref fix? * pro fix * pro fix? * move minio test provider to backend-core * update email builder to allow attachments * testing for sending files via smtp * use backend-core minio test container in server * handle different types of url * fix minio test provider * test with container host * lint * try different hostname? * Revert "try different hostname?" This reverts commit cfefdb8ded2b49462604053cf140e7292771c651. * fix issue with fetching of signed url with test minio * update autoamtion attachments to take filename and url * fix tests * pro ref * fix parsing of url object * pr comments and linting * pro ref * fix pro again * fix pro * account-portal * fix null issue * fix ref * ref * When sending a file attachment in email fetch it directly from our object store * add more checks to ensure we're working with a signed url * update test to account for direct object store read * formatting * fix time issues within test * update bucket and path extraction to regex * use const in regex * pro * Updating TTL handling in upload functions (#13539) * Updating TTL handling in upload functions * describe ttl type * account for ttl creation in existing buckets and update types * fix tests * pro * pro
2024-04-22 17:30:57 +02:00
}
}
} catch (err) {
if (triedParsing) {
data = responseTxt
raw = data as string
} else {
throw new Error(`Failed to parse response body: ${err}`)
}
}
REST file handling and SMTP automation block attachments (#13403) * handle files in rest connector * fetch presigned url and return * further updates to handle files in rest connector * remove unused important and fix extension bug * wrong expiry param * tests * add const for temp bucket * handle ttl on bucket * more bucket ttl work * split out fileresponse and xmlresponse into utils * lint * remove log * fix tests * some pr comments * update function naming and lint * adding back needed response for frontend * use fsp * handle different content-disposition and potential path traversal * add test container for s3 / minio * add test case for filename* and ascii filenames * move tests into separate describe * remove log * up timeout * switch to minio image instead of localstack * use minio image instead of s3 for testing * stream file upload instead * use streamUpload and update signatures * update bucketcreate return * throw real error * tidy up * pro * pro ref fix? * pro fix * pro fix? * move minio test provider to backend-core * update email builder to allow attachments * testing for sending files via smtp * use backend-core minio test container in server * handle different types of url * fix minio test provider * test with container host * lint * try different hostname? * Revert "try different hostname?" This reverts commit cfefdb8ded2b49462604053cf140e7292771c651. * fix issue with fetching of signed url with test minio * update autoamtion attachments to take filename and url * fix tests * pro ref * fix parsing of url object * pr comments and linting * pro ref * fix pro again * fix pro * account-portal * fix null issue * fix ref * ref * When sending a file attachment in email fetch it directly from our object store * add more checks to ensure we're working with a signed url * update test to account for direct object store read * formatting * fix time issues within test * update bucket and path extraction to regex * use const in regex * pro * Updating TTL handling in upload functions (#13539) * Updating TTL handling in upload functions * describe ttl type * account for ttl creation in existing buckets and update types * fix tests * pro * pro
2024-04-22 17:30:57 +02:00
const size = formatBytes(contentLength || "0")
const time = `${Math.round(performance.now() - this.startTimeMs)}ms`
headers = response.headers.raw()
for (let [key, value] of Object.entries(headers)) {
headers[key] = Array.isArray(value) ? value[0] : value
}
// Check if a pagination cursor exists in the response
let nextCursor = null
if (pagination?.responseParam) {
nextCursor = get(data, pagination.responseParam)
}
return {
data,
info: {
code: response.status,
size,
time,
},
extra: {
raw,
headers,
},
pagination: {
cursor: nextCursor,
},
}
}
getUrl(
path: string,
queryString: string,
2024-08-01 18:57:33 +02:00
pagination?: PaginationConfig,
paginationValues?: PaginationValues
): string {
// Add pagination params to query string if required
if (pagination?.location === "query" && paginationValues) {
const { pageParam, sizeParam } = pagination
const params = new URLSearchParams()
// Append page number or cursor param if configured
if (pageParam && paginationValues.page != null) {
params.append(pageParam, paginationValues.page as string)
}
// Append page size param if configured
if (sizeParam && paginationValues.limit != null) {
params.append(sizeParam, String(paginationValues.limit))
}
// Prepend query string with pagination params
let paginationString = params.toString()
if (paginationString) {
queryString = `${paginationString}&${queryString}`
}
}
2022-09-10 01:25:35 +02:00
if (queryString) {
2022-10-12 11:25:02 +02:00
// make sure the query string is fully encoded
queryString = "?" + qs.encode(qs.decode(queryString))
2022-09-10 01:25:35 +02:00
}
const main = `${path}${queryString}`
let complete = main
if (this.config.url && !main.startsWith("http")) {
complete = !this.config.url ? main : `${this.config.url}/${main}`
}
if (!complete.startsWith("http")) {
complete = `http://${complete}`
}
return complete
}
addBody(
bodyType: string,
body: string | any,
2024-08-01 18:57:33 +02:00
input: RequestInit,
pagination?: PaginationConfig,
paginationValues?: PaginationValues
): RequestInit {
if (!input.headers) {
input.headers = {}
}
if (bodyType === BodyType.NONE) {
return input
}
let error,
object: any = {},
string = ""
try {
if (body) {
string = typeof body !== "string" ? JSON.stringify(body) : body
object = typeof body === "object" ? body : JSON.parse(body)
}
} catch (err) {
error = err
}
// Util to add pagination values to a certain body type
const addPaginationToBody = (insertFn: Function) => {
if (pagination?.location === "body") {
if (pagination?.pageParam && paginationValues?.page != null) {
insertFn(pagination.pageParam, paginationValues.page)
}
if (pagination?.sizeParam && paginationValues?.limit != null) {
insertFn(pagination.sizeParam, paginationValues.limit)
}
}
}
switch (bodyType) {
case BodyType.TEXT:
// content type defaults to plaintext
input.body = string
break
case BodyType.ENCODED: {
const params = new URLSearchParams()
for (let [key, value] of Object.entries(object)) {
params.append(key, value as string)
}
addPaginationToBody((key: string, value: any) => {
params.append(key, value)
})
input.body = params
break
2024-03-19 16:58:25 +01:00
}
case BodyType.FORM_DATA: {
const form = new FormData()
for (let [key, value] of Object.entries(object)) {
form.append(key, value)
}
addPaginationToBody((key: string, value: any) => {
form.append(key, value)
})
input.body = form
break
2024-03-19 16:58:25 +01:00
}
case BodyType.XML:
if (object != null && Object.keys(object).length) {
string = new XmlBuilder().buildObject(object)
}
input.body = string
2024-08-01 18:57:33 +02:00
// @ts-ignore
input.headers["Content-Type"] = "application/xml"
break
case BodyType.JSON:
// if JSON error, throw it
if (error) {
throw "Invalid JSON for request body"
}
addPaginationToBody((key: string, value: any) => {
object[key] = value
})
input.body = JSON.stringify(object)
2024-08-01 18:57:33 +02:00
// @ts-ignore
input.headers["Content-Type"] = "application/json"
break
}
return input
}
2024-08-01 18:57:33 +02:00
getAuthHeaders(authConfigId?: string): { [key: string]: any } {
let headers: any = {}
if (this.config.authConfigs && authConfigId) {
const authConfig = this.config.authConfigs.filter(
c => c._id === authConfigId
)[0]
// check the config still exists before proceeding
// if not - do nothing
if (authConfig) {
let config
switch (authConfig.type) {
case RestAuthType.BASIC:
config = authConfig.config as RestBasicAuthConfig
headers.Authorization = `Basic ${Buffer.from(
`${config.username}:${config.password}`
).toString("base64")}`
break
case RestAuthType.BEARER:
config = authConfig.config as RestBearerAuthConfig
headers.Authorization = `Bearer ${config.token}`
break
}
}
}
return headers
}
async _req(query: RestQuery) {
const {
path = "",
queryString = "",
headers = {},
method = HttpMethod.GET,
disabledHeaders,
2024-08-01 18:57:33 +02:00
bodyType = BodyType.NONE,
requestBody,
authConfigId,
pagination,
paginationValues,
} = query
const authHeaders = this.getAuthHeaders(authConfigId)
this.headers = {
2024-08-01 18:57:33 +02:00
...(this.config.defaultHeaders || {}),
...headers,
...authHeaders,
}
if (disabledHeaders) {
for (let headerKey of Object.keys(this.headers)) {
if (disabledHeaders[headerKey]) {
delete this.headers[headerKey]
}
}
}
2024-08-01 18:57:33 +02:00
let input: RequestInit = { method, headers: this.headers }
input = this.addBody(
bodyType,
requestBody,
input,
pagination,
paginationValues
)
2022-09-10 01:25:35 +02:00
if (this.config.rejectUnauthorized == false) {
input.agent = new https.Agent({
rejectUnauthorized: false,
})
}
2022-09-09 23:14:28 +02:00
// Deprecated by rejectUnauthorized
2022-09-12 15:05:36 +02:00
if (this.config.legacyHttpParser) {
2024-08-01 18:57:33 +02:00
// NOTE(samwho): it seems like this code doesn't actually work because it requires
// node-fetch >=3, and we're not on that because upgrading to it produces errors to
// do with ESM that are above my pay grade.
2022-09-12 15:05:36 +02:00
// https://github.com/nodejs/node/issues/43798
2024-08-01 18:57:33 +02:00
// @ts-ignore
2022-09-12 15:05:36 +02:00
input.extraHttpOptions = { insecureHTTPParser: true }
}
this.startTimeMs = performance.now()
const url = this.getUrl(path, queryString, pagination, paginationValues)
if (await blacklist.isBlacklisted(url)) {
throw new Error("Cannot connect to URL.")
}
const response = await fetch(url, input)
return await this.parseResponse(response, pagination)
}
async create(opts: RestQuery) {
return this._req({ ...opts, method: HttpMethod.POST })
}
async read(opts: RestQuery) {
return this._req({ ...opts, method: HttpMethod.GET })
}
async update(opts: RestQuery) {
return this._req({ ...opts, method: HttpMethod.PUT })
}
async patch(opts: RestQuery) {
return this._req({ ...opts, method: HttpMethod.PATCH })
}
async delete(opts: RestQuery) {
return this._req({ ...opts, method: HttpMethod.DELETE })
}
}
export default {
schema: SCHEMA,
integration: RestIntegration,
}