UNPKG

@cocalc/project

Version:
151 lines 6.07 kB
"use strict"; /* * This file is part of CoCalc: Copyright © 2020 Sagemath, Inc. * License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); /* HTTP server for getting various information from Jupyter, without having to go through the websocket connection and messaging. This is useful, e.g., for big images, general info about all available kernels, sending signals, doing tab completions, and so on. */ const os_path = __importStar(require("path")); const awaiting_1 = require("awaiting"); const async_utils_node_1 = require("./async-utils-node"); const jupyter_blobs_sqlite_1 = require("./jupyter-blobs-sqlite"); const kernel_data_1 = require("./kernel-data"); const jupyter_1 = require("./jupyter"); const misc_1 = require("@cocalc/util/misc"); const logger_1 = __importDefault(require("@cocalc/backend/logger")); const winston = (0, logger_1.default)("jupyter-http-server"); const BASE = "/.smc/jupyter/"; function get_kernel(kernel_data, name) { for (const k of kernel_data) { if (k.name == name) return k; } return null; } function jupyter_kernel_info_handler(router) { router.get(BASE + "ipywidgets-get-buffer", async function (req, res) { try { const { path, model_id, buffer_path } = req.query; const kernel = (0, jupyter_1.get_existing_kernel)(path); if (kernel == null) { res.status(404).send(`kernel associated to ${path} does not exist`); return; } const buffer = kernel.ipywidgetsGetBuffer(model_id, buffer_path); if (buffer == null) { res .status(404) .send(`buffer associated to model ${model_id} at ${buffer_path} not known`); return; } res.status(200).send(buffer); } catch (err) { res.status(500).send(`Error getting ipywidgets buffer - ${err}`); } }); router.get(BASE + "ipywidgets-get-buffer-info", async function (req, res) { try { const { path, model_id, buffer_path } = req.query; const kernel = (0, jupyter_1.get_existing_kernel)(path); if (kernel == null) { res.status(404).send(`kernel associated to ${path} does not exist`); return; } const buffer = kernel.ipywidgetsGetBuffer(model_id, buffer_path); res.send({ path, model_id, buffer_path, buffer_length: buffer?.length, }); } catch (err) { res.status(500).send(`Error getting ipywidgets buffer info - ${err}`); } }); // we are only actually using this to serve up the logo. router.get(BASE + "kernelspecs/*", async function (req, res) { try { const kernel_data = await (0, kernel_data_1.get_kernel_data)(); let path = req.path.slice((BASE + "kernelspecs/").length).trim(); if (path.length === 0) { res.json(kernel_data); return; } const segments = path.split("/"); const name = segments[0]; const kernel = get_kernel(kernel_data, name); if (kernel == null) { const msg = `no such kernel '${name}'`; throw Error(msg); } const resource_dir = kernel.resource_dir; path = os_path.join(resource_dir, segments.slice(1).join("/")); path = os_path.resolve(path); if (!(0, misc_1.startswith)(path, resource_dir)) { // don't let user use .. or something to get any file on the server...! // (this really can't happen due to url rules already; just being super paranoid.) throw Error(`suspicious path '${path}'`); } if (await (0, async_utils_node_1.exists)(path)) { res.sendFile(path); } else { throw Error(`no such path '${path}'`); } } catch (err) { res.status(500).send(err.toString()); } }); } async function init() { while (true) { const blob_store = (0, jupyter_blobs_sqlite_1.get_blob_store)(); if (blob_store != null) { // Install handling for the blob store const router = blob_store.express_router(BASE); // Handler for Jupyter kernel info jupyter_kernel_info_handler(router); return router; } else { winston.warn("delaying setup, because BlobStore not available yet"); await (0, awaiting_1.delay)(5000); } } } exports.default = init; //# sourceMappingURL=http-server.js.map