fix(share): prevent crash when accessing /share on uninitialized setup (#9088)
Some checks are pending
Checks / main (push) Waiting to run
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Dev / Test development (push) Waiting to run
Dev / Build Docker image (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile) (push) Blocked by required conditions
Dev / Check Docker build (Dockerfile.alpine) (push) Blocked by required conditions
/ Check Docker build (Dockerfile) (push) Waiting to run
/ Check Docker build (Dockerfile.alpine) (push) Waiting to run
/ Build Docker images (Dockerfile, ubuntu-24.04-arm, linux/arm64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.alpine, ubuntu-latest, linux/amd64) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v7) (push) Blocked by required conditions
/ Build Docker images (Dockerfile.legacy, ubuntu-24.04-arm, linux/arm/v8) (push) Blocked by required conditions
/ Merge manifest lists (push) Blocked by required conditions
playwright / E2E tests on linux-arm64 (push) Waiting to run
playwright / E2E tests on linux-x64 (push) Waiting to run

This commit is contained in:
Elian Doran 2026-03-19 20:13:32 +02:00 committed by GitHub
commit 8d873c5869
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 28 additions and 1 deletions

View File

@ -1,6 +1,6 @@
import safeCompare from "safe-compare";
import type { Request, Response, Router } from "express";
import type { NextFunction, Request, Response, Router } from "express";
import shaca from "./shaca/shaca.js";
import shacaLoader from "./shaca/shaca_loader.js";
@ -10,6 +10,16 @@ import type SNote from "./shaca/entities/snote.js";
import type SAttachment from "./shaca/entities/sattachment.js";
import { getDefaultTemplatePath, renderNoteContent } from "./content_renderer.js";
import utils from "../services/utils.js";
import { isShareDbReady } from "./sql.js";
function assertShareDbReady(_req: Request, res: Response, next: NextFunction) {
if (!isShareDbReady()) {
res.status(503).send("The application is still initializing. Please try again in a moment.");
return;
}
next();
}
function addNoIndexHeader(note: SNote, res: Response) {
if (note.isLabelTruthy("shareDisallowRobotIndexing")) {
@ -115,6 +125,8 @@ function render404(res: Response) {
}
function register(router: Router) {
// Guard: if the share DB is not yet initialized, return 503 for all /share routes.
router.use("/share", assertShareDbReady);
function renderNote(note: SNote, req: Request, res: Response) {
if (!note) {

View File

@ -5,12 +5,14 @@ import dataDir from "../services/data_dir.js";
import sql_init from "../services/sql_init.js";
let dbConnection!: Database.Database;
let dbConnectionReady = false;
sql_init.dbReady.then(() => {
dbConnection = new Database(dataDir.DOCUMENT_PATH, {
readonly: true,
nativeBinding: process.env.BETTERSQLITE3_NATIVE_PATH || undefined
});
dbConnectionReady = true;
[`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `SIGTERM`].forEach((eventType) => {
process.on(eventType, () => {
@ -23,18 +25,31 @@ sql_init.dbReady.then(() => {
});
});
function assertDbReady(): void {
if (!dbConnectionReady) {
throw new Error("Share database connection is not yet ready. The application may still be initializing.");
}
}
function getRawRows<T>(query: string, params = []): T[] {
assertDbReady();
return dbConnection.prepare(query).raw().all(params) as T[];
}
function getRow<T>(query: string, params: string[] = []): T {
assertDbReady();
return dbConnection.prepare(query).get(params) as T;
}
function getColumn<T>(query: string, params: string[] = []): T[] {
assertDbReady();
return dbConnection.prepare(query).pluck().all(params) as T[];
}
export function isShareDbReady(): boolean {
return dbConnectionReady;
}
export default {
getRawRows,
getRow,