UNPKG

@strapi/data-transfer

Version:

Data transfer capabilities for Strapi

1 lines • 24.1 kB
{"version":3,"file":"utils.mjs","sources":["../../../../src/strapi/remote/handlers/utils.ts"],"sourcesContent":["import type { IncomingMessage } from 'node:http';\nimport { randomUUID } from 'crypto';\nimport type { Context } from 'koa';\nimport type { RawData, ServerOptions } from 'ws';\nimport { WebSocket, WebSocketServer } from 'ws';\n\nimport type { Handler, TransferState } from './abstract';\nimport type { Protocol } from '../../../../types';\nimport { ProviderError, ProviderTransferError } from '../../../errors/providers';\nimport { VALID_TRANSFER_COMMANDS, ValidTransferCommand } from './constants';\nimport { TransferMethod } from '../constants';\nimport { createDiagnosticReporter } from '../../../utils/diagnostic';\nimport { stringifyTransferWebSocketPayload } from '../../../utils/transfer-websocket-json';\n\ntype WSCallback = (client: WebSocket, request: IncomingMessage) => void;\n\nexport interface HandlerOptions {\n verify: (ctx: Context, scope?: TransferMethod) => Promise<void>;\n server?: ServerOptions;\n}\n\nexport const transformUpgradeHeader = (header = '') => {\n return header.split(',').map((s) => s.trim().toLowerCase());\n};\n\nlet timeouts: Record<string, number> | undefined;\n\nconst hasHttpServer = () => {\n // during server restarts, strapi may not have ever been defined at all, so we have to check it first\n return typeof strapi !== 'undefined' && !!strapi?.server?.httpServer;\n};\n\n// temporarily disable server timeouts while transfer is running\nconst disableTimeouts = () => {\n if (!hasHttpServer()) {\n return;\n }\n\n const { httpServer } = strapi.server;\n\n // save the original timeouts to restore after\n if (!timeouts) {\n timeouts = {\n headersTimeout: httpServer.headersTimeout,\n requestTimeout: httpServer.requestTimeout,\n };\n }\n\n httpServer.headersTimeout = 0;\n httpServer.requestTimeout = 0;\n\n strapi.log.info('[Data transfer] Disabling http timeouts');\n};\nconst resetTimeouts = () => {\n if (!hasHttpServer() || !timeouts) {\n return;\n }\n\n const { httpServer } = strapi.server;\n\n strapi.log.info('[Data transfer] Restoring http timeouts');\n httpServer.headersTimeout = timeouts.headersTimeout;\n httpServer.requestTimeout = timeouts.requestTimeout;\n};\n/**\n * Make sure that the upgrade header is a valid websocket one\n */\nexport const assertValidHeader = (ctx: Context) => {\n // if it's exactly what we expect, it's fine\n if (ctx.headers.upgrade === 'websocket') {\n return;\n }\n\n // check if it could be an array that still includes websocket\n const upgradeHeader = transformUpgradeHeader(ctx.headers.upgrade);\n\n // Sanitize user input before writing it to our logs\n const logSafeUpgradeHeader = JSON.stringify(ctx.headers.upgrade)\n ?.replace(/[^a-z0-9\\s.,|]/gi, '')\n .substring(0, 50);\n\n if (!upgradeHeader.includes('websocket')) {\n throw new Error(\n `Transfer Upgrade header expected 'websocket', found '${logSafeUpgradeHeader}'. Please ensure that your server or proxy is not modifying the Upgrade header.`\n );\n }\n\n /**\n * If there's more than expected but it still includes websocket, in theory it could still work\n * and could be necessary for their certain configurations, so we'll allow it to proceed but\n * log the unexpected behaviour in case it helps debug an issue\n * */\n strapi.log.info(\n `Transfer Upgrade header expected only 'websocket', found unexpected values: ${logSafeUpgradeHeader}`\n );\n};\n\nexport const isDataTransferMessage = (message: unknown): message is Protocol.Client.Message => {\n if (!message || typeof message !== 'object') {\n return false;\n }\n\n const { uuid, type } = message as Record<string, unknown>;\n\n if (typeof uuid !== 'string' || typeof type !== 'string') {\n return false;\n }\n\n if (!['command', 'transfer'].includes(type)) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Handle the upgrade to ws connection\n */\nexport const handleWSUpgrade = (wss: WebSocketServer, ctx: Context, callback: WSCallback) => {\n assertValidHeader(ctx);\n\n wss.handleUpgrade(ctx.req, ctx.request.socket, Buffer.alloc(0), (client, request) => {\n if (!client) {\n // If the WebSocket upgrade failed, destroy the socket to avoid hanging\n ctx.request.socket.destroy();\n return;\n }\n\n disableTimeouts();\n strapi.db.lifecycles.disable();\n strapi.log.info('[Data transfer] Disabling lifecycle hooks');\n\n // Create a connection between the client & the server\n wss.emit('connection', client, ctx.req);\n\n // Invoke the ws callback\n callback(client, request);\n });\n\n ctx.respond = false;\n};\n\n// Protocol related functions\n\nexport const handlerControllerFactory =\n <T extends Partial<Handler>>(implementation: (proto: Handler) => T) =>\n (options: HandlerOptions) => {\n const { verify, server: serverOptions } = options ?? {};\n\n const wss = new WebSocket.Server({ ...serverOptions, noServer: true });\n\n return async (ctx: Context) => {\n const cb: WSCallback = (ws) => {\n const state: TransferState = { id: undefined };\n const messageUUIDs = new Set<string>();\n const diagnostics = createDiagnosticReporter();\n\n const cannotRespondHandler = (err: unknown) => {\n strapi?.log?.error(\n '[Data transfer] Cannot send error response to client, closing connection'\n );\n strapi?.log?.error(err);\n try {\n ws.terminate();\n ctx.req.socket.destroy();\n } catch (err) {\n strapi?.log?.error('[Data transfer] Failed to close socket on error');\n }\n };\n\n const prototype: Handler = {\n // Transfer ID\n get transferID() {\n return state.id;\n },\n\n set transferID(id) {\n state.id = id;\n },\n\n // Started at\n get startedAt() {\n return state.startedAt;\n },\n\n set startedAt(timestamp) {\n state.startedAt = timestamp;\n },\n\n get response() {\n return state.response;\n },\n\n set response(response) {\n state.response = response;\n },\n\n get diagnostics() {\n return diagnostics;\n },\n\n addUUID(uuid) {\n messageUUIDs.add(uuid);\n },\n\n hasUUID(uuid) {\n return messageUUIDs.has(uuid);\n },\n\n isTransferStarted() {\n return this.transferID !== undefined && this.startedAt !== undefined;\n },\n\n assertValidTransfer() {\n const isStarted = this.isTransferStarted();\n\n if (!isStarted) {\n throw new Error('Invalid Transfer Process');\n }\n },\n\n assertValidTransferCommand(command: ValidTransferCommand) {\n const isDefined = typeof this[command] === 'function';\n const isValidTransferCommand = VALID_TRANSFER_COMMANDS.includes(command);\n\n if (!isDefined || !isValidTransferCommand) {\n throw new Error('Invalid transfer command');\n }\n },\n\n async respond(uuid, e, data) {\n let details = {};\n return new Promise<void>((resolve, reject) => {\n if (!uuid && !e) {\n reject(new Error('Missing uuid for this message'));\n return;\n }\n\n this.response = {\n uuid,\n data,\n e,\n };\n\n if (e instanceof ProviderError) {\n details = e.details;\n }\n\n const envelope: Record<string, unknown> = {\n uuid,\n data: data ?? null,\n error: e\n ? {\n code: e?.name ?? 'ERR',\n message: e?.message,\n details,\n }\n : null,\n };\n\n const payload = stringifyTransferWebSocketPayload(envelope);\n\n this.send(payload, (error) => (error ? reject(error) : resolve()));\n });\n },\n\n send(message, cb) {\n ws.send(message, cb);\n },\n confirm(message) {\n return new Promise((resolve, reject) => {\n const uuid = randomUUID();\n\n const payload = stringifyTransferWebSocketPayload({ uuid, data: message });\n\n this.send(payload, (error) => {\n if (error) {\n reject(error);\n }\n });\n\n const onResponse = (raw: RawData) => {\n const response = JSON.parse(raw.toString());\n\n if (response.uuid === uuid) {\n resolve(response.data ?? null);\n } else {\n ws.once('message', onResponse);\n }\n };\n\n ws.once('message', onResponse);\n });\n },\n\n async executeAndRespond(uuid, fn) {\n try {\n const response = await fn();\n await this.respond(uuid, null, response);\n } catch (e) {\n if (e instanceof Error) {\n await this.respond(uuid, e).catch(cannotRespondHandler);\n } else if (typeof e === 'string') {\n await this.respond(uuid, new ProviderTransferError(e)).catch(cannotRespondHandler);\n } else {\n await this.respond(\n uuid,\n new ProviderTransferError('Unexpected error', {\n error: e,\n })\n ).catch(cannotRespondHandler);\n }\n }\n },\n\n cleanup() {\n this.transferID = undefined;\n this.startedAt = undefined;\n this.response = undefined;\n },\n\n teardown() {\n this.cleanup();\n },\n\n verifyAuth(scope?: TransferMethod) {\n return verify(ctx, scope);\n },\n\n // Transfer commands\n init() {},\n end() {},\n status() {},\n\n // Default prototype implementation for events\n onMessage() {},\n onError() {},\n onClose() {},\n onInfo() {},\n onWarning() {},\n };\n\n const handler: Handler = Object.assign(Object.create(prototype), implementation(prototype));\n\n // Bind ws events to handler methods\n ws.on('close', async (...args) => {\n try {\n await handler.onClose(...args);\n } catch (err) {\n strapi?.log?.error('[Data transfer] Uncaught error closing connection');\n strapi?.log?.error(err);\n cannotRespondHandler(err);\n } finally {\n resetTimeouts();\n strapi.db.lifecycles.enable();\n strapi.log.info('[Data transfer] Restoring lifecycle hooks');\n }\n });\n ws.on('error', async (...args) => {\n try {\n await handler.onError(...args);\n } catch (err) {\n strapi?.log?.error('[Data transfer] Uncaught error in error handling');\n strapi?.log?.error(err);\n cannotRespondHandler(err);\n }\n });\n ws.on('message', async (...args) => {\n try {\n await handler.onMessage(...args);\n } catch (err) {\n strapi?.log?.error('[Data transfer] Uncaught error in message handling');\n strapi?.log?.error(err);\n cannotRespondHandler(err);\n }\n });\n\n diagnostics.onDiagnostic((diagnostic) => {\n const uuid = randomUUID();\n const payload = JSON.stringify({\n diagnostic,\n uuid,\n });\n\n handler.send(payload);\n });\n };\n\n try {\n handleWSUpgrade(wss, ctx, cb);\n } catch (err) {\n strapi?.log?.error('[Data transfer] Error in websocket upgrade request');\n strapi?.log?.error(err);\n }\n };\n };\n"],"names":["transformUpgradeHeader","header","split","map","s","trim","toLowerCase","timeouts","hasHttpServer","strapi","server","httpServer","disableTimeouts","headersTimeout","requestTimeout","log","info","resetTimeouts","assertValidHeader","ctx","headers","upgrade","upgradeHeader","logSafeUpgradeHeader","JSON","stringify","replace","substring","includes","Error","isDataTransferMessage","message","uuid","type","handleWSUpgrade","wss","callback","handleUpgrade","req","request","socket","Buffer","alloc","client","destroy","db","lifecycles","disable","emit","respond","handlerControllerFactory","implementation","options","verify","serverOptions","WebSocket","Server","noServer","cb","ws","state","id","undefined","messageUUIDs","Set","diagnostics","createDiagnosticReporter","cannotRespondHandler","err","error","terminate","prototype","transferID","startedAt","timestamp","response","addUUID","add","hasUUID","has","isTransferStarted","assertValidTransfer","isStarted","assertValidTransferCommand","command","isDefined","isValidTransferCommand","VALID_TRANSFER_COMMANDS","e","data","details","Promise","resolve","reject","ProviderError","envelope","code","name","payload","stringifyTransferWebSocketPayload","send","confirm","randomUUID","onResponse","raw","parse","toString","once","executeAndRespond","fn","catch","ProviderTransferError","cleanup","teardown","verifyAuth","scope","init","end","status","onMessage","onError","onClose","onInfo","onWarning","handler","Object","assign","create","on","args","enable","onDiagnostic","diagnostic"],"mappings":"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"}