@snap/camera-kit
Version:
Camera Kit Web
121 lines • 5.83 kB
JavaScript
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