Skip to content

Static asset routing silently shadows dynamic routes with dotted paths; duplicated content-type parsing #28

Description

@smiggleworth

Summary

Two issues in the static-asset serving path, both in serve.ts:

  1. Static asset guard shadows dynamic routes containing a dot. isAssetPath (src/serve.ts:39-41) is extname(pathname) !== "". When assets.root is configured, any GET/HEAD path containing a . is intercepted before application routing (serve.ts:100-158), and a missing file returns a 404 "without falling through to application routing" (confirmed at serve.ts:136-144, matches README:104-106). A route like /files/{name}.json or any dynamic segment that happens to contain a dot becomes permanently unreachable the moment static assets are enabled — with no per-route opt-out. The README documents the 404-without-fallthrough behavior but never mentions this collision with dynamic routing.
  2. Content-type sniffing is duplicated and can diverge. serve.ts:81-96 hand-rolls a regex (/^text\/html(?:;|$)/iu) to decide whether to inject cache-control: no-cache, instead of using askr-server's existing contentType/accepts helpers (@askrjs/server's src/http/media-types.ts). Two independently-maintained content-type parsers increase the chance of divergent edge-case handling (parameters, casing) between the two packages.

Requirements

  • Provide a way to exclude specific paths/patterns from the static-asset intercept (e.g. an assets.exclude option, or check application routes for a match before falling back to the 404-and-stop behavior).
  • Document the dot-path collision explicitly in the README until/unless the opt-out exists.
  • Replace the hand-rolled content-type regex with @askrjs/server's existing content-type parsing utility.

Acceptance Criteria

  • A dynamic route with a dotted path segment (e.g. /files/:name.json) is reachable even when assets.root is configured, either via an exclude option or via falling through to app routing on a static 404.
  • README documents the current/resulting behavior clearly enough that a user configuring assets.root won't be surprised.
  • serve.ts's content-type check for the no-cache header uses the shared @askrjs/server parser instead of a local regex.

Steps to Reproduce

  1. Configure assets.root pointing at a static directory.
  2. Define an application route GET /files/:name.json (or any path with a literal dot).
  3. Request /files/report.json.
  4. Observe: intercepted by the asset guard, 404s (file not found under assets.root), application handler is never reached.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions