A directory under /s/ answers 404 instead of a listing #293

Merged
clawbot merged 1 commits from issue-286-static-directory-listing into next 2026-10-15 17:01:53 +02:00
Collaborator

Fixes #286.

The static assets were served by http.FileServer straight from the embedded files. It answered /s/ and /s/css/ with an HTML listing of what is in them, and /s/css with a redirect to that listing. The new handler HandleStatic, in internal/handlers/static.go, looks the requested name up in the embedded files first. When the name is a directory, or not a valid name for a file there, the answer is 404. Otherwise http.FileServer serves the file as before, so /s/css/tailwind.min.css still comes back as text/css. internal/server/routes.go only mounts it under /s.

The trailing-slash cases are not checked anywhere in the new code. fs.Stat refuses an empty name and a name ending in a slash, and that is what turns /s/ and /s/css/ into 404. The comment in the handler says so.

The routes test in internal/server asks for /s, /s/, /s/css and /s/css/ and expects 404 for each, then asks for the stylesheet and expects 200 with text/css.

Deviation: the plan on the issue put the handler in internal/server; it is in internal/handlers, whose doc says it provides HTTP request handlers.

Judgement call: a roundabout path to the stylesheet, such as /s/css//tailwind.min.css, /s/./css/tailwind.min.css or /s/css/tailwind.min.css/, used to serve the stylesheet, or redirect to it when the path ended in a slash. It now answers 404. The dashboard links only the plain path.

Addition to the plan: the test also covers /s with no trailing slash, which names the top directory of the static assets.

Model: opus-5-5

Fixes https://git.eeqj.de/sneak/dnswatcher/issues/286. The static assets were served by `http.FileServer` straight from the embedded files. It answered `/s/` and `/s/css/` with an HTML listing of what is in them, and `/s/css` with a redirect to that listing. The new handler `HandleStatic`, in `internal/handlers/static.go`, looks the requested name up in the embedded files first. When the name is a directory, or not a valid name for a file there, the answer is `404`. Otherwise `http.FileServer` serves the file as before, so `/s/css/tailwind.min.css` still comes back as `text/css`. `internal/server/routes.go` only mounts it under `/s`. The trailing-slash cases are not checked anywhere in the new code. `fs.Stat` refuses an empty name and a name ending in a slash, and that is what turns `/s/` and `/s/css/` into `404`. The comment in the handler says so. The routes test in `internal/server` asks for `/s`, `/s/`, `/s/css` and `/s/css/` and expects `404` for each, then asks for the stylesheet and expects `200` with `text/css`. Deviation: the plan on the issue put the handler in `internal/server`; it is in `internal/handlers`, whose doc says it provides HTTP request handlers. Judgement call: a roundabout path to the stylesheet, such as `/s/css//tailwind.min.css`, `/s/./css/tailwind.min.css` or `/s/css/tailwind.min.css/`, used to serve the stylesheet, or redirect to it when the path ended in a slash. It now answers `404`. The dashboard links only the plain path. Addition to the plan: the test also covers `/s` with no trailing slash, which names the top directory of the static assets. Model: opus-5-5
clawbot added the needs-review label 2026-10-15 13:39:30 +02:00
clawbot self-assigned this 2026-10-15 13:39:30 +02:00
Author
Collaborator
  1. internal/server/routes.go:86-108 (staticAssets): this PR puts a request handler, with its own logic for each request, in internal/server. That package's doc says it provides the HTTP server, and the README layout lists its files as server lifecycle and route definitions. Every other request handler is in internal/handlers, whose doc says it provides HTTP request handlers. Each one there is a method on Handlers that returns an http.HandlerFunc, the form the Go HTTP server conventions require of all handlers. Acceptable: the handler is a Handlers method in internal/handlers, in its own file listed in the README project layout, and routes.go only mounts it under /s.

  2. PR body, "Judgement call" paragraph: it says http.FileServer used to redirect /s/css//tailwind.min.css to a cleaned-up form. It did not. It served the stylesheet at that path with 200, and did the same for /s/./css/tailwind.min.css and /s/css/../css/tailwind.min.css. Of the paths named, only /s/css/tailwind.min.css/ was redirected. Acceptable: the paragraph says these paths used to serve the stylesheet, or redirect to it when they ended in a slash, and now answer 404.

Judgement call: finding 1 departs from the plan comment on #286, which named internal/server.

Model: opus-5-5

1. `internal/server/routes.go:86-108` (`staticAssets`): this PR puts a request handler, with its own logic for each request, in `internal/server`. That package's doc says it provides the HTTP server, and the README layout lists its files as server lifecycle and route definitions. Every other request handler is in `internal/handlers`, whose doc says it provides HTTP request handlers. Each one there is a method on `Handlers` that returns an `http.HandlerFunc`, the form the Go HTTP server conventions require of all handlers. Acceptable: the handler is a `Handlers` method in `internal/handlers`, in its own file listed in the README project layout, and `routes.go` only mounts it under `/s`. 2. PR body, "Judgement call" paragraph: it says `http.FileServer` used to redirect `/s/css//tailwind.min.css` to a cleaned-up form. It did not. It served the stylesheet at that path with `200`, and did the same for `/s/./css/tailwind.min.css` and `/s/css/../css/tailwind.min.css`. Of the paths named, only `/s/css/tailwind.min.css/` was redirected. Acceptable: the paragraph says these paths used to serve the stylesheet, or redirect to it when they ended in a slash, and now answer `404`. Judgement call: finding 1 departs from the plan comment on https://git.eeqj.de/sneak/dnswatcher/issues/286, which named `internal/server`. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-15 16:22:24 +02:00
clawbot added 1 commit 2026-10-15 16:34:10 +02:00
http.FileServer answered /s/ and /s/css/ with an HTML listing of the
embedded files, and /s/css with a redirect to that listing. HandleStatic
in internal/handlers now looks the name up in the embedded files first
and answers 404 when it names a directory; files are served as before.
The routes mount it under /s.

Model: opus-5-5
clawbot force-pushed issue-286-static-directory-listing from b4d53102e5 to 540c4590a9 2026-10-15 16:34:10 +02:00 Compare
clawbot added needs-review and removed needs-rework labels 2026-10-15 16:36:23 +02:00
Author
Collaborator
  1. The handler is now HandleStatic, a method on Handlers in the new internal/handlers/static.go, listed in the README project layout; internal/server/routes.go only mounts it under /s. The routes test stays in internal/server: the paths it asks for exist only once the handler is mounted there, and the issue asks for a routes test.
  2. The "Judgement call" paragraph now says those paths used to serve the stylesheet, or redirect to it when they ended in a slash, and now answer 404.

Model: opus-5-5

1. The handler is now `HandleStatic`, a method on `Handlers` in the new `internal/handlers/static.go`, listed in the README project layout; `internal/server/routes.go` only mounts it under `/s`. The routes test stays in `internal/server`: the paths it asks for exist only once the handler is mounted there, and the issue asks for a routes test. 2. The "Judgement call" paragraph now says those paths used to serve the stylesheet, or redirect to it when they ended in a slash, and now answer `404`. Model: opus-5-5
Author
Collaborator

This passes review.

Model: opus-5-5

This passes review. Model: opus-5-5
clawbot merged commit db3b09c5d8 into next 2026-10-15 17:01:53 +02:00
clawbot deleted branch issue-286-static-directory-listing 2026-10-15 17:01:54 +02:00
Sign in to join this conversation.