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/next/lib/share/get-vhost-info.ts
Views: 687
import getPool from "@cocalc/database/pool";1import { getLogger } from "@cocalc/backend/logger";2import LRU from "lru-cache";34const logger = getLogger("get-vhost-info");56export interface Auth {7name: string;8pass: string; // password-hash9}1011export type VirtualHostInfo = { [path: string]: Auth[] };1213interface HostInfo {14project_id: string;15path: string;16auth: VirtualHostInfo;17cross_origin_isolation?: boolean;18}1920// This could get called a LOT on the same host that is not special21// for the server, and also the list of public projects that have22// vhost info is very small (e.g., like 10 of them) and at least23// right now only something that is manually changed! We thus cache24// the answer for 1 minute. If we change our use of vhosts, we can25// revisit this parameter.2627const cache = new LRU<string, HostInfo | null>({28ttl: 1000 * 60,29max: 1000,30});3132export default async function getVirtualHostInfo(33vhost: string34): Promise<HostInfo | null | undefined> {35if (cache.has(vhost)) {36//logger.debug("using cache");37return cache.get(vhost);38}3940// long: once a vhost is set, it's unlikely to change for a while, since it literally41// requires updating DNS entries to have any impact.42const pool = getPool("long");4344// Get the database entry that describes the public path with given vhost.45// NOTE: we are assuming there is at most one with a given vhost. If there46// are more, behavior is not defined, but that will get logged.47// As an optimization, we also check if vhost is null, to quickly remove the majority of entries (gives a 1000x speedup in prod).48const query = `SELECT project_id, path, auth, cross_origin_isolation49FROM public_paths50WHERE disabled IS NOT TRUE51AND vhost IS NOT NULL52AND $1::TEXT=ANY(string_to_array(vhost,','))`;53// logger.debug('query = ', query);5455try {56const { rows } = await pool.query(query, [vhost]);5758if (59rows.length == 0 ||60rows[0].project_id == null ||61rows[0].path == null62) {63// logger.debug("no valid virtual vhost=%s", vhost);64cache.set(vhost, null);65return null;66}67if (rows.length > 1) {68logger.warn("WARNING: multiple virtual host entries for vhost=%s", vhost);69}70const { project_id, path, auth, cross_origin_isolation } = rows[0]; // is a weird data type, which is why we don't just return it.71const r = { project_id, path, auth, cross_origin_isolation };72cache.set(vhost, r);73return r;74} catch (err) {75logger.error(`error querying for vhost ${vhost}`, err);76return null;77}78}798081