Skip to content

Fix static_assets mount matching and the filesystem provider #19

Description

@yorkin-bot

Summary

The current static asset middleware can intercept unrelated routes, panic on short paths, skip directory indexes, and return files without a MIME type.

Relevant code:

Reproduction

Create a dedicated fixture directory next to the reproduction package. Do not expose the repository or process working directory as the static root:

testdata/
└── public/
    ├── index.html
    └── app.txt

For example, put index fixture in index.html and asset fixture in app.txt, then serve only that directory:

async fn main {
  let app = @mocket.new()
  app.static_assets("/assets", @static_file.new("testdata/public"))
  app.get("/api", _ => "api ok")
  app.listen("127.0.0.1:49288")
}

Observed on main@c545db2, native backend:

Request Result
GET /assets 404
GET /assets/ 404 instead of serving testdata/public/index.html
GET /assets/app.txt 200 with asset fixture, but no Content-Type
GET /api empty reply; process exits with PanicError

The first condition in static_assets calls next() when match_path(path, url) succeeds. For an unrelated shorter URL, execution instead reaches event.req.url[path.length():], which aborts on the out-of-range slice.

The default filesystem provider compounds this:

  • get_meta returns Some for every candidate without checking the filesystem, so probing stops before index/fallthrough logic can work.
  • get_type always returns None.
  • file reads use synchronous moonbitlang/x/fs inside an async request path;
  • all I/O errors are collapsed to 404.

Expected behavior

  • Match the mount as a path prefix with a segment boundary.
  • Never slice until the mount relationship and bounds are validated.
  • Resolve a safe relative path confined to the configured root.
  • Make get_meta return None for absent candidates and provide real size/mtime/type metadata.
  • Serve configured directory indexes correctly.
  • Use supported async filesystem I/O, or clearly document unavoidable blocking behavior.
  • Preserve fallthrough and distinguish not-found from other I/O failures.
  • Add black-box tests for mounted paths, unrelated routes, short URLs, indexes, MIME types, HEAD, and fallthrough.

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