Commit Graph
1 Commits
Author SHA1 Message Date
aneurinandClaude Sonnet 5 7a6e1aa6a8 fix middleware races, ReadFile error paths, and lib.Coalesce
Build / build-and-push (push) Successful in 1m13s
PR Checks / checks (pull_request) Successful in 1m36s
Closes #8, #9, #10; partially addresses #11.

middlewares (#8):
- Log: log once from the Middleware closure after the handler returns
  instead of spawning a goroutine per Write (data race on the shared
  LogWriter, multiple log lines per request). Bodiless responses
  (204/304/redirects) are now logged too, and the status-class switch has
  a default branch so a stray sub-100 status can't nil-deref the event.
- logWriter forwards http.Flusher / http.Hijacker / io.ReaderFrom so
  streaming handlers and the file server keep their fast paths.
- Both middlewares use the closure idiom rather than storing next on a
  shared instance, so they're safe to register on more than one chain.
- CorsOrigin now honours its argument: a comma-separated allow-list,
  with "*" meaning allow-any. Wired to a new --allow-origin flag that
  defaults to "*" (unchanged behaviour out of the box).

ReadFile (#9):
- Add the missing returns after GetFile / open failures (the old code
  fell through to os.ReadFile(nil path) and wrote a second body).
- Hand off to http.ServeContent for Content-Type, Range and
  If-Modified-Since, and set Content-Disposition: inline so the embedded
  audio player streams instead of downloading (the download button
  already uses the HTML download attribute).

lib.Coalesce (#10):
- Constrain to comparable and compare against a fresh zero value. The
  old IsZero type switch compared an any against untyped constants, so
  every narrow numeric type (int8..int64, uint*, float32) reported
  non-zero and never fell back. IsZero is removed (was unused elsewhere).

tests (#11, high-value/easy set):
- lib.Coalesce table across every numeric width, string, bool, pointer.
- database.Migrate against a temp sqlite: schema created, recorded once,
  second call is a no-op.
- types.NewFile: id = sha256(path), hash = sha256(contents), scan fields
  copied, and the missing-file path still yields an id.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-07 17:22:00 +01:00