Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/hub/servers/app/blobs.ts
Views: 687
import { Router } from "express";1import { database } from "../database";2import { is_valid_uuid_string } from "@cocalc/util/misc";3import { database_is_working } from "@cocalc/hub/hub_register";4import { callback2 } from "@cocalc/util/async-utils";5import { getLogger } from "@cocalc/hub/logger";67const logger = getLogger("hub:servers:app:blobs");8export default function init(router: Router) {9// return uuid-indexed blobs (mainly used for graphics)10router.get("/blobs/*", async (req, res) => {11logger.debug(`${JSON.stringify(req.query)}, ${req.path}`);12const uuid = `${req.query.uuid}`;13if (req.headers["if-none-match"] === uuid) {14res.sendStatus(304);15return;16}17if (!is_valid_uuid_string(uuid)) {18res.status(404).send(`invalid uuid=${uuid}`);19return;20}21if (!database_is_working()) {22res.status(404).send("can't get blob -- not connected to database");23return;24}2526try {27const data = await callback2(database.get_blob, { uuid });28if (data == null) {29res.status(404).send(`blob ${uuid} not found`);30} else {31const filename = req.path.slice(req.path.lastIndexOf("/") + 1);32if (req.query.download != null) {33// tell browser to download the link as a file instead34// of displaying it in browser35res.attachment(filename);36} else {37res.type(filename);38}39// Cache as long as possible (e.g., One year in seconds), since40// what we are returning is defined by a sha1 hash, so cannot change.41res.set("Cache-Control", `public, max-age=${365 * 24 * 60 * 60}`);42// "public means that the response may be cached by clients and any43// intermediary caches (like CDNs). max-age determines the amount44// of time (in seconds) a client should cache the response."45// The maximum value that you can set for max-age is 1 year46// (in seconds), which is compliant with the HTTP/1.147// specifications (RFC2616)."48res.set("ETag", uuid);49res.send(data);50}51} catch (err) {52logger.error(`internal error ${err} getting blob ${uuid}`);53res.status(500).send(`internal error: ${err}`);54}55});56}575859