UNPKG

edgerender

Version:
120 lines 4.6 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Assets = void 0; const lite_1 = __importDefault(require("mime/lite")); const utils_1 = require("./utils"); const response_1 = require("./response"); class Assets { path; log; prefix; manifest; kv_namespace; security_headers; headers; constructor(config, security_headers, log) { this.path = config.path || '/assets/'; if (!this.path.startsWith('/') || !this.path.endsWith('/')) { throw Error('static path must start and end with "/"'); } this.prefix = new RegExp(`^${utils_1.escape_regex(this.path)}`); if (typeof config.content_manifest === 'string') { this.manifest = JSON.parse(config.content_manifest); } else { this.manifest = null; } this.kv_namespace = config.kv_namespace; this.security_headers = security_headers; this.headers = { 'cache-control': config.cache_control || 'public, max-age=86400', }; this.log = log; } is_static_path(pathname) { return pathname.startsWith(this.path); } async response(request, pathname) { // stripe leading slashes and "assets to match the format in static_manifest const asset_path = pathname.replace(this.prefix, ''); let content_key; if (this.manifest) { content_key = this.manifest[asset_path]; if (!content_key) { throw this.not_found_error(pathname); } } else { content_key = asset_path; } if (this.kv_namespace == undefined) { console.warn('KV namespace not defined, static assets not available'); throw this.not_found_error(pathname); } const body = await this.kv_namespace.get(content_key, 'arrayBuffer'); if (body === null) { // if we have a manifest then it's unexpected that the key doesn't exist, otherwise it's just a 404 if (this.manifest) { // TODO log to sentry console.error(`content_key "${content_key}" found for asset_path "${pathname}", but no value in the KV store`); } throw this.not_found_error(pathname); } else { return { body, mime_type: this.mime_type(pathname), headers: this.headers, }; } } not_found_error(pathname) { return new response_1.HttpError(404, `static asset "${pathname}" not found`); } async cached_proxy(request, url, custom_mime_type = null) { const cache_key = `cached-file:${url}`; if (this.kv_namespace == undefined) { throw new Error(`KV namespace not defined, static assets not available`); } const cache_value = await this.kv_namespace.getWithMetadata(cache_key, 'stream'); if (cache_value.value) { const metadata = cache_value.metadata || {}; return { body: cache_value.value, mime_type: custom_mime_type || metadata.mime_type || response_1.MimeTypes.octetStream, headers: this.headers, }; } if (this.log) { console.debug(`"${url}" not yet cached, downloading`); } const r = await fetch(url, request); if (r.status != 200) { throw new response_1.HttpError(502, `Error getting "${url}", upstream response: ${r.status}`); } const mime_type = custom_mime_type || r.headers.get('content-type') || response_1.MimeTypes.octetStream; const body = await r.arrayBuffer(); await this.kv_namespace.put(cache_key, body, { expirationTtl: 3600 * 24 * 30, metadata: { mime_type } }); return { body, mime_type, headers: this.headers }; } mime_type(pathname) { const m = pathname.toLocaleLowerCase().match(/\.([a-z]+)$/); let mime_type = undefined; if (m) { const ext = m[0]; mime_type = known_mime_types[ext]; if (!mime_type) { mime_type = lite_1.default.getType(ext); } } return mime_type || response_1.MimeTypes.octetStream; } } exports.Assets = Assets; const known_mime_types = { '.ico': response_1.MimeTypes.ico, }; //# sourceMappingURL=assets.js.map