UNPKG

zephyr-agent

Version:
90 lines (89 loc) • 3.94 kB
import "node:module"; import { ZEPHYR_API_ENDPOINT, ZE_API_ENDPOINT_HOST, ZE_IS_PREVIEW, safe_json_parse } from "zephyr-edge-contract"; import { ZeErrors, ZephyrError } from "../errors/index.mjs"; import { ze_log } from "../logging/debug.mjs"; import { cleanTokens } from "../node-persist/token.mjs"; import { redactString, redactUrl, safeStringifyForLogging } from "../security/redaction.mjs"; import { fetchWithRetries } from "./fetch-with-retries.mjs"; function applyApiHost(url) { const is_preview = ZE_IS_PREVIEW(); const ze_api_endpoint_host = ZE_API_ENDPOINT_HOST(); const zephyr_api_endpoint = ZEPHYR_API_ENDPOINT(); if (is_preview && url.host === ze_api_endpoint_host) url.searchParams.set('api_host', zephyr_api_endpoint); return url; } function parseUrl(urlStr) { if ('string' == typeof urlStr) return applyApiHost(new URL(urlStr)); { if (urlStr instanceof URL) return applyApiHost(urlStr); const url = new URL(urlStr.path, urlStr.base); for (const [key, value] of Object.entries(urlStr.query))url.searchParams.append(key, String(value)); return applyApiHost(url); } } function redactResponse(url, options, data, response, startTime = Date.now()) { return [ `[${options.method || 'GET'}][${redactUrl(url)}]: ${Date.now() - startTime}ms`, data?.length ? ` - ${((data.length ?? 0) / 1024).toFixed(2)}kb` : '', void 0 !== response ? `Response: ${redactString(String(response))}` : '', `Options: ${safeStringifyForLogging(options)}` ].join('\n'); } async function makeHttpRequest(url, options = {}, data) { const startTime = Date.now(); const { credentialToken, skipTokenCleanup = false, ...requestOptions } = options; try { const response = await fetchWithRetries(url, { ...requestOptions, body: data }); const resText = await response.text(); if (401 === response.status) { const authenticationError = new ZephyrError(ZeErrors.ERR_AUTH_ERROR, { message: 'The request authentication is invalid or expired.' }); if (!skipTokenCleanup) try { await cleanTokens(credentialToken); } catch (error) { ze_log.error('Failed to remove rejected authentication credentials:', error); } throw authenticationError; } if (403 === response.status) throw new ZephyrError(ZeErrors.ERR_AUTH_FORBIDDEN_ERROR, { message: 'The authenticated account does not have access to this target.' }); const message = redactResponse(url, requestOptions, data, resText, startTime); if ('Not Implemented' === resText.trim()) throw new ZephyrError(ZeErrors.ERR_UNKNOWN, { message: 'Not implemented yet. Please get in contact with our support.' }); if (!url.pathname.includes('application/logs')) ze_log.http(message); const resData = safe_json_parse(resText) ?? resText; if (!response.status || response.status >= 300) throw new ZephyrError(ZeErrors.ERR_HTTP_ERROR, { status: response.status, url: redactUrl(url), content: 'string' == typeof resData ? redactString(resData) : safeStringifyForLogging(resData), method: requestOptions.method?.toUpperCase() ?? 'GET' }); return [ true, null, resData ]; } catch (error) { return [ false, error ]; } } function makeRequest(urlStr, options = {}, data) { const url = parseUrl(urlStr); return makeHttpRequest(url, options, data); } async function unwrapResponse(response) { const [ok, error, data] = await response; if (!ok) throw error; return data; } export { makeHttpRequest, makeRequest, parseUrl, unwrapResponse }; //# sourceMappingURL=http-request.mjs.map