Skip to content

fix(sendFile): surface resolved path in "No such file" error; clarify no auto-versioning (#257)#330

Open
naorpeled wants to merge 2 commits into
jeremydaly:mainfrom
naorpeled:fix/257-no-versioning-clarify-sendfile-error
Open

fix(sendFile): surface resolved path in "No such file" error; clarify no auto-versioning (#257)#330
naorpeled wants to merge 2 commits into
jeremydaly:mainfrom
naorpeled:fix/257-no-versioning-clarify-sendfile-error

Conversation

@naorpeled

@naorpeled naorpeled commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

Closes #257.

Background

#257 reported that a route /:v/schema.json returned {"error":"No such file"} when hitting /v1/schema.json, and asked for an option to disable versioning.

Investigation showed the premise doesn't hold: lambda-api has no automatic version routing or stripping — in the current code or anywhere in git history. Route matching (src/lib/request.js) is plain segment-by-segment traversal. Reproduced against the reporter's exact setup:

api.get('/:v/schema.json', (req, res) => res.json({ v: req.params.v }));
// GET /v1/schema.json  -> 200 { "v": "v1" }   ✅ already works

The "No such file" was not a routing error — it's emitted by res.sendFile() on ENOENT in the reporter's own handler (they most likely passed req.path = /v1/schema.json to sendFile, so the full path was looked up on disk). Because the error message was terse and pathless, it was easy to misread as a "versioning" problem.

So rather than add a no-op flag, this PR fixes the actual pain and locks in the behavior.

Changes

  • src/lib/response.jssendFile ENOENT errors now include the resolved path, e.g. No such file: ./test-missing.txt, so the real cause is self-evident. FileError already carried e.path; it just never reached the message.
  • __tests__/versioning.unit.js (new) — regression tests proving version-like segments route literally (/v1/schema.jsonparams.v === 'v1'), a non-version segment behaves identically, an extra segment still 404s, and documents the base: 'v1' + leading :param collision caveat (→ 405).
  • __tests__/sendFile.unit.js, __tests__/download.unit.js — updated the two "Missing file" assertions to the new message.
  • README.md — documented that lambda-api does no automatic version handling, that base: 'v1' collides with a leading :param (prefer a non-version base + register({ prefix })), and how res.sendFile(path, { root }) resolves paths.

Heads-up for review

The error-message change surfaces the file path in the HTTP error body. It's helpful for debugging and mirrors Node's own ENOENT, but it is a minor change to a public error string — happy to make it opt-in or revert that part if you'd prefer it stay terse.

Verification

Full suite green: npm run build + tsd + 489 passed / 4 skipped across 28 suites. Prettier + ESLint clean on touched files.

… no auto-versioning (jeremydaly#257)

Issue jeremydaly#257 reported that a `/:v/schema.json` route returned
`{"error":"No such file"}` at `/v1/schema.json` and asked for an option to
disable "versioning". Investigation showed lambda-api has no version
routing/stripping — `/:v/schema.json` already matches `/v1/schema.json` and
captures `req.params.v === "v1"`. The error actually came from `res.sendFile()`
throwing ENOENT in the reporter's own handler; the terse, pathless message is
what led to the misdiagnosis.

- sendFile ENOENT errors now include the resolved path
  (e.g. `No such file: ./test-missing.txt`) so the real cause is obvious.
- Add __tests__/versioning.unit.js locking in literal version-segment routing
  and documenting the `base: 'v1'` + leading `:param` collision caveat.
- Update the two existing sendFile/download "Missing file" assertions.
- Document in the README that lambda-api performs no automatic version
  handling, and how `res.sendFile(path, { root })` resolves paths.
@naorpeled naorpeled force-pushed the fix/257-no-versioning-clarify-sendfile-error branch from 3b77322 to fb470a9 Compare July 4, 2026 14:31
@naorpeled naorpeled requested a review from Copilot July 4, 2026 14:34

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses confusion from issue #257 by clarifying that lambda-api does not do any automatic “version” path handling, and by making res.sendFile() missing-file errors more self-explanatory so they aren’t misread as routing failures.

Changes:

  • Update sendFile() ENOENT handling to include the missing path in the "No such file" error message.
  • Add a new regression test suite verifying version-like segments (e.g. /v1/...) are matched literally, plus a documented base: 'v1' caveat.
  • Update README guidance and adjust existing unit tests to the new error string.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/lib/response.js Changes ENOENT error message emitted by sendFile() to include a path string.
README.md Documents that there is no automatic version stripping and clarifies sendFile({ root }) path resolution.
tests/versioning.unit.js Adds regression tests for literal matching of version-like segments and base + leading :param collision behavior.
tests/sendFile.unit.js Updates missing-file assertion to match the new error message.
tests/download.unit.js Updates missing-file assertion to match the new error message.

Comment thread src/lib/response.js
Comment thread README.md Outdated
Comment thread __tests__/versioning.unit.js
…all, add v2/ALB versioning tests

- response.js: strip opts.root prefix and reduce absolute paths to basename
  in the client-visible "No such file" error to avoid leaking server paths
  (e.g. /var/task/...); full e.path is still preserved on FileError for logs
- README: note sendFile root+path is literal concatenation and needs a
  trailing/leading slash to avoid ./static + file.txt -> ./staticfile.txt
- versioning.unit.js: assert version-like segments match literally for API
  Gateway v2 (rawPath) and ALB events, not just v1
- sendFile.unit.js: regression tests for absolute-root and absolute-path
  sanitization
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.

Is it possible to disable versioning?

2 participants