Skip to content

feat(api): let download verify the file starts with an expected signature - #152

Open
arminfauland wants to merge 1 commit into
Disane87:mainfrom
arminfauland:feat/download-verify-magic
Open

feat(api): let download verify the file starts with an expected signature#152
arminfauland wants to merge 1 commit into
Disane87:mainfrom
arminfauland:feat/download-verify-magic

Conversation

@arminfauland

Copy link
Copy Markdown

Problem

When a session expires or a bot check kicks in, the other side usually answers with HTTP 200 and an HTML page rather than an error status. response.ok is true, the buffer is non-empty, so the download action happily writes it under the requested name.

The result is an invoice.pdf whose content is <!DOCTYPE html><html>…. Nothing in the pipeline notices — in my case three such files reached a document management system and were only found days later by hand.

Solution

An optional expectMagic parameter:

{
  "action": "download",
  "params": {
    "url": "{{previousData.invoiceUrl}}",
    "path": "./downloads",
    "filename": "invoice-{{previousData.orderId}}.pdf",
    "expectMagic": "%PDF"
  }
}

If the content does not start with that signature, the file is not written, the action logs what it actually received, and returns null — so a skipIf can react to it.

❌ invoice-306-1234567.pdf: expected content to start with "%PDF" but found "<!DO" — file not written

Both write paths are covered:

  • the remote fetch — checked on the buffer before writeFileSync
  • the local file:// copy — only the first bytes are read via openSync/readSync, not the whole file

Without the parameter nothing changes, so existing configurations are unaffected. That is covered by a test rather than just asserted.

Tests

4 new cases in download.action.spec.ts:

case expectation
remote content starts with %PDF written
remote content is an HTML page not written, null, error logged
expectMagic absent, HTML content written — unchanged behaviour
local file with wrong signature not copied, null

nx lint api clean, full API suite green (84 files / 1420 tests).

Docs

Parameter table row plus a section explaining the failure mode, in both EN and DE (user-guide/actions/download.mdx). astro build passes — 90 pages, 2 languages.

…ture

When a session expires or a bot check kicks in, the other side usually
answers with HTTP 200 and an HTML page rather than an error status. The
download action wrote that page under the requested name, producing an
"invoice.pdf" whose content is "<!DOCTYPE html>". Downstream processing
notices late or not at all — in our case three such files reached a
document management system before anyone spotted them.

Adds an optional `expectMagic` parameter:

    "params": {
      "url": "…",
      "path": "./downloads",
      "filename": "invoice.pdf",
      "expectMagic": "%PDF"
    }

If the content does not start with the given signature, the file is not
written, the actual bytes are logged, and the action returns null so a
skipIf can react. Both download paths are covered — the remote fetch and
the local file:// copy, where only the first bytes are read rather than
the whole file.

Without the parameter behaviour is unchanged, so existing configurations
are unaffected.

Tests: 4 new cases (match, mismatch, parameter absent, local file).
Docs: parameter table and a section in EN and DE.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LixHBPkhb8h5oDdMqSG4se
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant