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