From dde8f778774ab756edb51e1c4e2a208e80b70629 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Thu, 15 Feb 2024 14:48:47 +0000 Subject: [PATCH] Type workerRequests.ts --- .../src/logging/correlation/correlation.ts | 13 +++- .../server/src/utilities/workerRequests.ts | 78 ++++++++++++++----- 2 files changed, 70 insertions(+), 21 deletions(-) diff --git a/packages/backend-core/src/logging/correlation/correlation.ts b/packages/backend-core/src/logging/correlation/correlation.ts index 0498bd43d5..2ee02c16a9 100644 --- a/packages/backend-core/src/logging/correlation/correlation.ts +++ b/packages/backend-core/src/logging/correlation/correlation.ts @@ -1,10 +1,19 @@ +import { HeaderInit, Headers } from "node-fetch" import { Header } from "../../constants" const correlator = require("correlation-id") -export const setHeader = (headers: any) => { +export const setHeader = (headers: HeaderInit) => { const correlationId = correlator.getId() - if (correlationId) { + if (!correlationId) { + return + } + + if (headers instanceof Headers) { + headers.set(Header.CORRELATION_ID, correlationId) + } else if (Array.isArray(headers)) { + headers.push([Header.CORRELATION_ID, correlationId]) + } else { headers[Header.CORRELATION_ID] = correlationId } } diff --git a/packages/server/src/utilities/workerRequests.ts b/packages/server/src/utilities/workerRequests.ts index 5612084216..d3c5cad161 100644 --- a/packages/server/src/utilities/workerRequests.ts +++ b/packages/server/src/utilities/workerRequests.ts @@ -1,4 +1,10 @@ -import { Response, default as fetch } from "node-fetch" +import { + Response, + default as fetch, + type RequestInit, + Headers, + HeadersInit, +} from "node-fetch" import env from "../environment" import { checkSlashesInUrl } from "./index" import { @@ -10,29 +16,61 @@ import { } from "@budibase/backend-core" import { Ctx, User, EmailInvite } from "@budibase/types" -export function request(ctx?: Ctx, request?: any) { - if (!request.headers) { - request.headers = {} +function ensureHeadersIsObject(headers: HeadersInit | undefined): Headers { + if (headers instanceof Headers) { + return headers } + const headersObj = new Headers() + if (headers === undefined) { + return headersObj + } + + if (Array.isArray(headers)) { + for (const [key, value] of headers) { + headersObj.append(key, value) + } + } else { + for (const key in headers) { + headersObj.append(key, headers[key]) + } + } + return headersObj +} + +export function request(request: RequestInit & { ctx?: Ctx }): RequestInit { + const ctx = request.ctx + request.headers = ensureHeadersIsObject(request.headers) + if (!ctx) { - request.headers[constants.Header.API_KEY] = coreEnv.INTERNAL_API_KEY + if (coreEnv.INTERNAL_API_KEY) { + request.headers.set(constants.Header.API_KEY, coreEnv.INTERNAL_API_KEY) + } } else if (ctx.headers) { // copy all Budibase utilised headers over - copying everything can have // side effects like requests being rejected due to odd content types etc for (let header of Object.values(constants.Header)) { - if (ctx.headers[header]) { - request.headers[header] = ctx.headers[header] + const value = ctx.headers[header] + if (value === undefined) { + continue + } + + if (Array.isArray(value)) { + for (let v of value) { + request.headers.append(header, v) + } + } else { + request.headers.set(header, value) } } } // apply tenancy if its available if (tenancy.isTenantIdSet()) { - request.headers[constants.Header.TENANT_ID] = tenancy.getTenantId() + request.headers.set(constants.Header.TENANT_ID, tenancy.getTenantId()) } if (request.body && Object.keys(request.body).length > 0) { - request.headers["Content-Type"] = "application/json" + request.headers.set("Content-Type", "application/json") request.body = typeof request.body === "object" ? JSON.stringify(request.body) @@ -44,6 +82,7 @@ export function request(ctx?: Ctx, request?: any) { // add x-budibase-correlation-id header logging.correlation.setHeader(request.headers) + delete request.ctx return request } @@ -93,9 +132,9 @@ export async function sendSmtpEmail({ // tenant ID will be set in header const response = await fetch( checkSlashesInUrl(env.WORKER_URL + `/api/global/email/send`), - request(undefined, { + request({ method: "POST", - body: { + body: JSON.stringify({ email: to, from, contents, @@ -105,7 +144,7 @@ export async function sendSmtpEmail({ purpose: "custom", automation, invite, - }, + }), }) ) return checkResponse(response, "send email") @@ -115,7 +154,8 @@ export async function removeAppFromUserRoles(ctx: Ctx, appId: string) { const prodAppId = dbCore.getProdAppID(appId) const response = await fetch( checkSlashesInUrl(env.WORKER_URL + `/api/global/roles/${prodAppId}`), - request(ctx, { + request({ + ctx, method: "DELETE", }) ) @@ -126,7 +166,7 @@ export async function allGlobalUsers(ctx: Ctx) { const response = await fetch( checkSlashesInUrl(env.WORKER_URL + "/api/global/users"), // we don't want to use API key when getting self - request(ctx, { method: "GET" }) + request({ ctx, method: "GET" }) ) return checkResponse(response, "get users", { ctx }) } @@ -135,7 +175,7 @@ export async function saveGlobalUser(ctx: Ctx) { const response = await fetch( checkSlashesInUrl(env.WORKER_URL + "/api/global/users"), // we don't want to use API key when getting self - request(ctx, { method: "POST", body: ctx.request.body }) + request({ ctx, method: "POST", body: ctx.request.body }) ) return checkResponse(response, "save user", { ctx }) } @@ -146,7 +186,7 @@ export async function deleteGlobalUser(ctx: Ctx) { env.WORKER_URL + `/api/global/users/${ctx.params.userId}` ), // we don't want to use API key when getting self - request(ctx, { method: "DELETE" }) + request({ ctx, method: "DELETE" }) ) return checkResponse(response, "delete user", { ctx }) } @@ -157,7 +197,7 @@ export async function readGlobalUser(ctx: Ctx): Promise { env.WORKER_URL + `/api/global/users/${ctx.params.userId}` ), // we don't want to use API key when getting self - request(ctx, { method: "GET" }) + request({ ctx, method: "GET" }) ) return checkResponse(response, "get user", { ctx }) } @@ -167,7 +207,7 @@ export async function getChecklist(): Promise<{ }> { const response = await fetch( checkSlashesInUrl(env.WORKER_URL + "/api/global/configs/checklist"), - request(undefined, { method: "GET" }) + request({ method: "GET" }) ) return checkResponse(response, "get checklist") } @@ -175,7 +215,7 @@ export async function getChecklist(): Promise<{ export async function generateApiKey(userId: string) { const response = await fetch( checkSlashesInUrl(env.WORKER_URL + "/api/global/self/api_key"), - request(undefined, { method: "POST", body: { userId } }) + request({ method: "POST", body: JSON.stringify({ userId }) }) ) return checkResponse(response, "generate API key") }