UNPKG

@snap/camera-kit

Version:
121 lines 5.83 kB
import { Injectable } from "@snap/ts-inject"; import { RemoteApiInfo } from "../../generated-proto/pb_schema/camera_kit/v3/features/remote_api_info"; import { ResponseCode, responseCodeToNumber, } from "../../generated-proto/pb_schema/lenses/remote_api/remote_api_service"; import { getLogger } from "../../logger/logger"; import { Count } from "../../metrics/operational/Count"; import { joinMetricNames } from "../../metrics/operational/Metric"; import { createUriRequestProcessor } from "../uriRequestProcessor"; import { extractSchemeAndRoute } from "../UriHandlers"; const logger = getLogger("RemoteApiServices"); const uriResponseOkCode = 200; const apiResponseStatusHeader = ":sc_lens_api_status"; const apiBinaryContentType = "application/octet-stream"; const remoteApiInfoProtobufTypeUrl = "type.googleapis.com/com.snap.camerakit.v3.features.RemoteApiInfo"; const remoteApiUploadImageSpecId = "af3f69c8-2e62-441f-8b1c-d3956f7b336c"; const statusToResponseCodeMap = { success: ResponseCode.SUCCESS, redirected: ResponseCode.REDIRECTED, badRequest: ResponseCode.BAD_REQUEST, accessDenied: ResponseCode.ACCESS_DENIED, notFound: ResponseCode.NOT_FOUND, timeout: ResponseCode.TIMEOUT, requestTooLarge: ResponseCode.REQUEST_TOO_LARGE, serverError: ResponseCode.SERVER_ERROR, cancelled: ResponseCode.CANCELLED, proxyError: ResponseCode.PROXY_ERROR, }; export const remoteApiServicesFactory = Injectable("remoteApiServices", () => { const remoteApiServices = []; return remoteApiServices; }); function getFirstRequestHandler(services, remoteApiRequest, lens) { for (const service of services) { try { return service.getRequestHandler(remoteApiRequest, lens); } catch (error) { logger.warn("Client's Remote API request handler factory threw an error.", error); } } return undefined; } export function createRemoteApiUriHandler(registeredServices, sessionState, lensState, lensRepository, metrics) { const registeredServiceMap = new Map(); for (const service of registeredServices) { const existingServices = registeredServiceMap.get(service.apiSpecId) || []; registeredServiceMap.set(service.apiSpecId, [...existingServices, service]); } return createUriRequestProcessor({ uri: "app://remote-api/performApiRequest", lensState, sessionState, createLensRequestState(_request, lens) { var _a, _b; return { supportedSpecIds: new Set([ ...((_b = (_a = lensRepository.getLensMetadata(lens.id)) === null || _a === void 0 ? void 0 : _a.featureMetadata) !== null && _b !== void 0 ? _b : []) .filter((feature) => feature.typeUrl === remoteApiInfoProtobufTypeUrl) .flatMap((any) => RemoteApiInfo.decode(any.value).apiSpecIds), remoteApiUploadImageSpecId, ]), }; }, processRequest({ request, reply, lens, setCancellationHandler, state }) { var _a; const { route } = extractSchemeAndRoute(request.uri); const [specId, endpointIdWithQuery] = route.split("/").slice(2); const [endpointId] = endpointIdWithQuery.split("?"); const dimensions = { specId }; const reportSingleCount = (name) => { metrics.setOperationalMetrics(Count.count(joinMetricNames(["lens", "remote-api", name]), 1, dimensions)); }; reportSingleCount("requests"); if (!(state === null || state === void 0 ? void 0 : state.supportedSpecIds.has(specId))) return; const remoteApiRequest = { apiSpecId: specId, body: request.data, endpointId, parameters: request.metadata, }; let requestHandler = getFirstRequestHandler((_a = registeredServiceMap.get(specId)) !== null && _a !== void 0 ? _a : [], remoteApiRequest, lens); if (!requestHandler) return; reportSingleCount("handled-requests"); let cancellationHandler = undefined; try { cancellationHandler = requestHandler((response) => { var _a; reportSingleCount("responses"); const responseCode = (_a = statusToResponseCodeMap[response.status]) !== null && _a !== void 0 ? _a : ResponseCode.UNRECOGNIZED; const uriResponse = { code: uriResponseOkCode, description: "", contentType: apiBinaryContentType, data: response.body, metadata: Object.assign(Object.assign({}, response.metadata), { [apiResponseStatusHeader]: responseCodeToNumber(responseCode).toString() }), }; reply(uriResponse); }); } catch (error) { logger.warn("Client's Remote API request handler threw an error.", error); } if (typeof cancellationHandler === "function") { setCancellationHandler(() => { try { cancellationHandler(); } catch (error) { logger.warn("Client's Remote API request cancellation handler threw an error.", error); } }); } }, processInternalError(error) { logger.error(error); metrics.setOperationalMetrics(Count.count(joinMetricNames(["lens", "remote-api", "errors"]), 1)); }, }); } //# sourceMappingURL=remoteApiUriHandler.js.map