Skip to content

Harden backupRoutes download handler: async fs check + headersSent guard #3524

Description

@Yeraze

Surfaced in the #3523 (#3502 batch 2) review. Both are pre-existing behaviors carried verbatim from server.ts into the new src/server/routes/backupRoutes.ts module — now isolated and easy to fix.

  1. Sync fs.existsSync in an async handler — the GET /system/backup/download/:dirname handler does const fs = await import('fs'); if (!fs.existsSync(backupPath)), which blocks the event loop. Switch to fs.promises.access/stat (the fs/promises import is already used elsewhere in the module).

  2. res.status(500).json() after headers sent — the archiver error handler can fire after archive.pipe(res) has started streaming, throwing "Cannot set headers after they are sent." Guard with if (!res.headersSent).

Optional while here: a happy-path test for GET /system/backup/download/:dirname (tar.gz streaming) and for GET /apprise/urls (+ its ENOENT fallback), and promoting the per-request await import('archiver'|'fs') to static top-level imports.

Low priority / robustness only — no current functional regression.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions