@directus/api
Version:
Directus is a real-time API and App dashboard for managing SQL database content
90 lines (88 loc) • 4.33 kB
JavaScript
import async_handler_default from "../utils/async-handler.js";
import { useLogger } from "../logger/index.js";
import { getMilliseconds } from "../utils/get-milliseconds.js";
import { getCache, setCacheValue } from "../cache.js";
import database_default from "../database/index.js";
import { ExportService } from "../services/export.js";
import { getCacheControlHeader } from "../utils/get-cache-headers.js";
import { getCacheKey } from "../utils/get-cache-key.js";
import { stringByteSize } from "../utils/get-string-byte-size.js";
import { permissionsCacheable } from "../utils/permissions-cacheable.js";
import { useEnv } from "@directus/env";
import { getDateTimeFormatted } from "@directus/utils";
import { parse } from "bytes";
//#region src/middleware/respond.ts
const respond = async_handler_default(async (req, res) => {
const env = useEnv();
const logger = useLogger();
const { cache } = getCache();
const cacheInstance = res.locals["cacheInstance"] || cache;
const cacheTTL = res.locals["cacheTTL"] ?? getMilliseconds(env["CACHE_TTL"]);
const hasCustomCache = !!res.locals["cacheInstance"];
let exceedsMaxSize = false;
if (env["CACHE_VALUE_MAX_SIZE"] !== false) {
const valueSize = res.locals["payload"] ? stringByteSize(JSON.stringify(res.locals["payload"])) : 0;
const maxSize = parse(env["CACHE_VALUE_MAX_SIZE"]);
if (maxSize !== null) exceedsMaxSize = valueSize > maxSize;
}
if (hasCustomCache ? res.locals["cache"] !== false && cacheInstance && !req.sanitizedQuery.export && exceedsMaxSize === false : (req.method.toLowerCase() === "get" || req.originalUrl?.startsWith("/graphql")) && req.originalUrl?.startsWith("/auth") === false && env["CACHE_ENABLED"] === true && cache && !req.sanitizedQuery.export && res.locals["cache"] !== false && exceedsMaxSize === false && await permissionsCacheable(req.collection, {
knex: database_default(),
schema: req.schema
}, req.accountability)) {
const key = await getCacheKey(req);
try {
await setCacheValue(cacheInstance, key, res.locals["payload"], cacheTTL);
await setCacheValue(cacheInstance, `${key}__expires_at`, { exp: Date.now() + cacheTTL });
} catch (err) {
logger.warn(err, `[cache] Couldn't set key ${key}. ${err}`);
}
res.setHeader("Cache-Control", getCacheControlHeader(req, cacheTTL, !hasCustomCache, true));
res.setHeader("Vary", "Origin, Cache-Control");
} else if (res.locals["cacheTTL"] !== void 0) {
res.setHeader("Cache-Control", getCacheControlHeader(req, cacheTTL, false, true));
res.setHeader("Vary", "Origin, Cache-Control");
} else {
res.setHeader("Cache-Control", "no-cache");
res.setHeader("Vary", "Origin, Cache-Control");
}
if (req.sanitizedQuery.export) {
const exportService = new ExportService({
accountability: req.accountability ?? null,
schema: req.schema
});
let filename = "";
if (req.collection) filename += req.collection;
else filename += "Export";
filename += " " + getDateTimeFormatted();
if (req.sanitizedQuery.export === "json") {
res.attachment(`${filename}.json`);
res.set("Content-Type", "application/json");
return res.status(200).send(exportService.transform(res.locals["payload"]?.data, "json"));
}
if (req.sanitizedQuery.export === "xml") {
res.attachment(`${filename}.xml`);
res.set("Content-Type", "text/xml");
return res.status(200).send(exportService.transform(res.locals["payload"]?.data, "xml"));
}
if (req.sanitizedQuery.export === "csv") {
res.attachment(`${filename}.csv`);
res.set("Content-Type", "text/csv");
return res.status(200).send(exportService.transform(res.locals["payload"]?.data, "csv"));
}
if (req.sanitizedQuery.export === "csv_utf8") {
res.attachment(`${filename}.csv`);
res.set("Content-Type", "text/csv; charset=utf-8");
return res.status(200).send(exportService.transform(res.locals["payload"]?.data, "csv_utf8"));
}
if (req.sanitizedQuery.export === "yaml") {
res.attachment(`${filename}.yaml`);
res.set("Content-Type", "text/yaml");
return res.status(200).send(exportService.transform(res.locals["payload"]?.data, "yaml"));
}
}
if (Buffer.isBuffer(res.locals["payload"])) return res.end(res.locals["payload"]);
else if (res.locals["payload"]) return res.json(res.locals["payload"]);
else return res.status(204).end();
});
//#endregion
export { respond };