@cocalc/hub
Version:
CoCalc: Backend webserver component
100 lines (99 loc) • 4.45 kB
JavaScript
;
/*
Serve the Next.js application server, which provides:
- the share server for public_paths
- the landing pages
- ... and more?!
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const path_1 = require("path");
// @ts-ignore -- TODO: typescript doesn't like @cocalc/next/init (it is a js file).
const init_1 = __importDefault(require("@cocalc/next/init"));
const handle_raw_1 = __importDefault(require("@cocalc/next/lib/share/handle-raw"));
const logger_1 = require("@cocalc/hub/logger");
const share_redirect_1 = __importDefault(require("./share-redirect"));
const landing_redirect_1 = __importDefault(require("./landing-redirect"));
const base_path_1 = __importDefault(require("@cocalc/backend/base-path"));
const database_1 = require("../database");
const async_utils_1 = require("@cocalc/util/async-utils");
async function init(app) {
const winston = (0, logger_1.getLogger)("nextjs");
winston.info("Initializing the nextjs server...");
const handler = await (0, init_1.default)({ basePath: base_path_1.default });
const shareServer = await runShareServer();
const shareBasePath = (0, path_1.join)(base_path_1.default, "share");
if (shareServer) {
// We create a redirect middleware and a raw/download
// middleware, since the share server will be fully available.
// IMPORTANT: all files are also served with download:true, so that
// they don't get rendered with potentially malicious content.
// The only way we could allow this is to serve all raw content
// from a separate domain, e.g., raw.cocalc.com. That would be
// reasonable on cocalc.com, but to ensure this for all on-prem,
// etc. servers is definitely too much, so we just disable this.
// For serving actual raw content, the solution will be to use
// a vhost.
// 1: The raw static server:
const raw = (0, path_1.join)(shareBasePath, "raw");
app.all((0, path_1.join)(raw, "*"), (req, res, next) => {
try {
(0, handle_raw_1.default)({
...parseURL(req, raw),
req,
res,
next,
download: true /* do not change this by default -- see above. */,
});
}
catch (_err) {
res.status(404).end();
}
});
// 2: The download server -- just like raw, but files always get sent via download.
const download = (0, path_1.join)(shareBasePath, "download");
app.all((0, path_1.join)(download, "*"), (req, res, next) => {
try {
(0, handle_raw_1.default)({
...parseURL(req, download),
req,
res,
next,
download: true,
});
}
catch (_err) {
res.status(404).end();
}
});
// 3: Redirects for backward compat; unfortunately there's slight
// overhead for doing this on every request.
app.all((0, path_1.join)(shareBasePath, "*"), (0, share_redirect_1.default)(shareBasePath));
}
const landingRedirect = (0, landing_redirect_1.default)();
app.all((0, path_1.join)(base_path_1.default, "index.html"), landingRedirect);
app.all((0, path_1.join)(base_path_1.default, "doc*"), landingRedirect);
app.all((0, path_1.join)(base_path_1.default, "policies*"), landingRedirect);
// The next.js server that serves everything else.
winston.info("Now using next.js packages/share handler to handle all endpoints not otherwise handled");
app.all("*", handler);
}
exports.default = init;
function parseURL(req, base) {
let url = req.url.slice(base.length + 1);
let i = url.indexOf("/");
if (i == -1) {
url = url + "/";
i = url.length - 1;
}
return { id: url.slice(0, i), path: decodeURI(url.slice(i + 1)) };
}
async function runShareServer() {
const { rows } = await (0, async_utils_1.callback2)(database_1.database._query, {
query: "SELECT value FROM server_settings WHERE name='share_server'",
});
return rows.length > 0 && rows[0].value == "yes";
}
//# sourceMappingURL=next.js.map