UNPKG

@snap/camera-kit

Version:
149 lines 6.08 kB
import { __awaiter } from "tslib"; import { getLogger } from "../../logger/logger"; import { namedError } from "../../namedErrors"; import { createUriRequestProcessor } from "../uriRequestProcessor"; import { isPromise } from "../../common/typeguards"; import { requestValidationErrorName, validateRequest } from "./httpValidators"; const logger = getLogger("lensHttpHandler"); const lensHttpHandlerErrorName = "LensHttpHandlerError"; const lensHttpHandlerError = namedError(lensHttpHandlerErrorName); const allowedResponseHeaders = [ "Accept-Ranges", "Cache-Control", "Content-Language", "Content-Length", "Content-Type", "Date", "ETag", "Expires", "Last-Modified", "Location", ]; const requestHeadersToExclude = ["x-sc-lenses-remote-api-spec-id"]; export function createHttpUriHandler(lensState, sessionState, remoteApiSpecsClient, customLentFetchHandler) { let allowlistPromise = undefined; return createUriRequestProcessor({ uri: ["http://", "https://"], lensState, sessionState, processRequest({ request, lens, reply, setCancellationHandler }) { return __awaiter(this, void 0, void 0, function* () { allowlistPromise = allowlistPromise !== null && allowlistPromise !== void 0 ? allowlistPromise : getAllowlist(remoteApiSpecsClient); const allowlist = yield allowlistPromise; handleHttpUriRequest(request, lens, reply, setCancellationHandler, allowlist, customLentFetchHandler); }); }, processInternalError(error) { logger.error(error); }, }); } function getAllowlist(remoteApiSpecsClient) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { const result = yield remoteApiSpecsClient.getRemoteApiSpecs({}); if (!result.ok) throw new Error("Failed getting Remote API specs.", { cause: result.unwrapErr() }); return (_b = (_a = result.unwrap().message) === null || _a === void 0 ? void 0 : _a.remoteApiSpecs) !== null && _b !== void 0 ? _b : []; }); } export function handleHttpUriRequest(request, lens, reply, setCancellationHandler, allowlist, customLensHttpHandler) { return __awaiter(this, void 0, void 0, function* () { try { validateRequest(request, allowlist); const { url, init } = mapLensToFetchRequest(request); const abortController = new AbortController(); init.signal = abortController.signal; setCancellationHandler(() => abortController.abort()); let response; if (customLensHttpHandler) { const handlerName = "lensHttpHandler"; try { const { uri, identifier, method, metadata, data } = request; const responsePromise = customLensHttpHandler(url, init, { url: uri, identifier, method, data, headers: metadata, lens, }); if (!isPromise(responsePromise)) { throw lensHttpHandlerError(`The '${handlerName}' callback provided to Camera Kit must return a Promise.`); } response = yield responsePromise; } catch (error) { error = error instanceof Error && error.name === lensHttpHandlerErrorName ? error : lensHttpHandlerError(`The '${handlerName}' callback provided to Camera Kit configuration failed.`, error); throw error; } } else { response = yield fetch(url, init); } reply(yield mapFetchToLensResponse(response)); } catch (error) { if (error instanceof Error && error.name === lensHttpHandlerErrorName) { logger.warn(error); reply(getErrorResponse("LensHttpHandlerError", `The lens HTTP request handler provided to Camera Kit failed.`)); } else if (error instanceof Error && error.name === requestValidationErrorName) { logger.warn(error); reply(getErrorResponse("RequestValidationError", error.message)); } else { logger.error(error); reply(getErrorResponse("UnknownError", "An unknown error occurred.")); } } }); } function getErrorResponse(errorType, message) { return { code: 400, description: "", contentType: "text/plain", metadata: { "x-camera-kit-error-type": errorType, }, data: new TextEncoder().encode(message), }; } export function mapLensToFetchRequest({ uri, method, metadata, data }) { const headers = new Headers(metadata); for (const header of requestHeadersToExclude) { headers.delete(header); } return { url: uri, init: { headers: Object.fromEntries(headers.entries()), body: method !== "GET" && method !== "HEAD" && method !== undefined ? data : undefined, method, }, }; } export function mapFetchToLensResponse(response) { var _a; return __awaiter(this, void 0, void 0, function* () { const metadata = {}; for (const allowedHeader of allowedResponseHeaders) { const value = response.headers.get(allowedHeader); if (value) { metadata[allowedHeader.toLowerCase()] = value; } } return { code: response.status, description: "", contentType: ((_a = response.headers.get("Content-Type")) !== null && _a !== void 0 ? _a : ""), metadata, data: yield response.arrayBuffer(), }; }); } //# sourceMappingURL=httpUriHandler.js.map