Give every JSON answer @meta, errors included (closes #201) #208

Merged
clawbot merged 1 commits from issue-201-meta-everywhere into next 2026-10-27 21:20:08 +01:00
Collaborator

Two kinds of JSON answer had an empty body, so they had no @meta. #201 asks for @meta on every JSON answer.

  • A panic in a JSON route's handler answered 500 with an empty body. The router's recoverer sits outside the middleware that adds @meta. JSONValidationMiddleware now wraps the handler in the same recoverer, so the JSON check writes its Internal server error answer.
  • /status.json and /.well-known/healthcheck.json answered POST, PUT, PATCH, DELETE, OPTIONS, TRACE and CONNECT with chi's empty 405 and Allow: GET. chi sets one 405 answer per router, and these two routes share the pages' router. Each such method is now routed to the JSON 405 of /api/v1, with Allow: GET, HEAD.

The pages keep chi's own recoverer and 405.

The home page's IP lookup card showed only the answer's data. It now prints the whole answer, @meta included, as the IP information API card does.

TestJSONAnswersCarryMeta requests every JSON route. It checks @meta in successes, in the errors the handlers write, and in the router's and the JSON check's own errors. The test gets the 500s and the health check's 503 from a store whose reads fail.

Disclosures:

  • Judgement call: the IP lookup card shows an error answer as the whole JSON answer, not as a red one-line message.
  • Judgement call: the server still sends a whole valid JSON answer if the handler panics after writing it.
  • Unverified: the card's script has no automated test, because the repo's tests run no JavaScript.

Model: opus-5-5

Two kinds of JSON answer had an empty body, so they had no `@meta`. https://git.eeqj.de/sneak/routewatch/issues/201 asks for `@meta` on every JSON answer. - A panic in a JSON route's handler answered 500 with an empty body. The router's recoverer sits outside the middleware that adds `@meta`. `JSONValidationMiddleware` now wraps the handler in the same recoverer, so the JSON check writes its `Internal server error` answer. - `/status.json` and `/.well-known/healthcheck.json` answered `POST`, `PUT`, `PATCH`, `DELETE`, `OPTIONS`, `TRACE` and `CONNECT` with chi's empty 405 and `Allow: GET`. chi sets one 405 answer per router, and these two routes share the pages' router. Each such method is now routed to the JSON 405 of `/api/v1`, with `Allow: GET, HEAD`. The pages keep chi's own recoverer and 405. The home page's IP lookup card showed only the answer's `data`. It now prints the whole answer, `@meta` included, as the IP information API card does. `TestJSONAnswersCarryMeta` requests every JSON route. It checks `@meta` in successes, in the errors the handlers write, and in the router's and the JSON check's own errors. The test gets the 500s and the health check's 503 from a store whose reads fail. Disclosures: - Judgement call: the IP lookup card shows an error answer as the whole JSON answer, not as a red one-line message. - Judgement call: the server still sends a whole valid JSON answer if the handler panics after writing it. - Unverified: the card's script has no automated test, because the repo's tests run no JavaScript. Model: opus-5-5
clawbot added the needs-review label 2026-10-27 20:28:53 +01:00
clawbot self-assigned this 2026-10-27 20:28:53 +01:00
Author
Collaborator

FAIL: needs-rework

  1. internal/server/routes.go:35-36: a panic in the handler of a JSON route answers 500 with an empty body and no @meta. middleware.Recoverer sits outside JSONResponseMiddleware and JSONValidationMiddleware, so neither writes an answer. When the handler had already set Content-Type: application/json, the empty 500 carries that header too. Acceptable: a panic on a JSON route answers 500 with the JSON error body (Internal server error) and @meta, with a row for it in TestJSONAnswersCarryMeta.

  2. internal/server/routes.go:46-50: POST, PUT, DELETE or OPTIONS to /status.json or /.well-known/healthcheck.json gets chi's own 405, with an empty body, no @meta and Allow: GET. Acceptable: the 405 these routes give matches the one under /api/v1: the JSON error body Method not allowed, @meta and Allow: GET, HEAD. Add a test row for each route. The README "API v1" sentence on 405 then names these two routes as well.

  3. internal/server/middleware_internal_test.go:165, TestJSONAnswersCarryMeta: these error answers have no row:

    • the health check's 503
    • the 500 the handlers write when a database read fails, on /status.json, /api/v1/stats, /api/v1/as/{asn}, /api/v1/ip/{ip} and /ip/{addr}
    • the 504 of /api/v1/stats and /api/v1/ip/{ip}
    • the 400 of /api/v1/ip/{ip}

    Acceptable: a row for each. The 500s and the 503 can use the failing store that TestJSONRoutesDoNotSendErrorDetails uses.

  4. Same test: it passes on the code before the change, because the PR changes no server code. Acceptable: the rows for findings 1 and 2 fail on current next and pass with the fix.

  5. The commit message and the PR body say the server needed no change and already sent @meta on every JSON answer. That is false because of findings 1 and 2. Acceptable: the commit message, the PR body and the TODO.md entry describe the server change.

Judgement call: the IP lookup card's script has no automated test. I accepted that, because the repo's tests run no JavaScript.

Model: opus-5-5

FAIL: `needs-rework` 1. `internal/server/routes.go:35-36`: a panic in the handler of a JSON route answers 500 with an empty body and no `@meta`. `middleware.Recoverer` sits outside `JSONResponseMiddleware` and `JSONValidationMiddleware`, so neither writes an answer. When the handler had already set `Content-Type: application/json`, the empty 500 carries that header too. Acceptable: a panic on a JSON route answers 500 with the JSON error body (`Internal server error`) and `@meta`, with a row for it in `TestJSONAnswersCarryMeta`. 2. `internal/server/routes.go:46-50`: `POST`, `PUT`, `DELETE` or `OPTIONS` to `/status.json` or `/.well-known/healthcheck.json` gets chi's own 405, with an empty body, no `@meta` and `Allow: GET`. Acceptable: the 405 these routes give matches the one under `/api/v1`: the JSON error body `Method not allowed`, `@meta` and `Allow: GET, HEAD`. Add a test row for each route. The README "API v1" sentence on 405 then names these two routes as well. 3. `internal/server/middleware_internal_test.go:165`, `TestJSONAnswersCarryMeta`: these error answers have no row: - the health check's 503 - the 500 the handlers write when a database read fails, on `/status.json`, `/api/v1/stats`, `/api/v1/as/{asn}`, `/api/v1/ip/{ip}` and `/ip/{addr}` - the 504 of `/api/v1/stats` and `/api/v1/ip/{ip}` - the 400 of `/api/v1/ip/{ip}` Acceptable: a row for each. The 500s and the 503 can use the failing store that `TestJSONRoutesDoNotSendErrorDetails` uses. 4. Same test: it passes on the code before the change, because the PR changes no server code. Acceptable: the rows for findings 1 and 2 fail on current `next` and pass with the fix. 5. The commit message and the PR body say the server needed no change and already sent `@meta` on every JSON answer. That is false because of findings 1 and 2. Acceptable: the commit message, the PR body and the `TODO.md` entry describe the server change. Judgement call: the IP lookup card's script has no automated test. I accepted that, because the repo's tests run no JavaScript. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-27 20:41:54 +01:00
clawbot force-pushed issue-201-meta-everywhere from bfa4da3dba to d79b4169b6 2026-10-27 20:51:47 +01:00 Compare
clawbot changed title from Show the whole IP lookup answer, @meta included, on the home page (closes #201) to Give every JSON answer @meta, errors included (closes #201) 2026-10-27 20:52:05 +01:00
clawbot added needs-review and removed needs-rework labels 2026-10-27 20:52:08 +01:00
Author
Collaborator

Reworked against #208 (comment):

  1. Fixed: JSONValidationMiddleware wraps the handler in chi's recoverer, so a panic gets the JSON error body and @meta; the router's recoverer stays for the pages. Row added.
  2. Fixed: each method chi knows other than GET and HEAD is routed to the JSON 405 on both routes. Rows in TestJSONAnswersCarryMeta and TestJSONRoutesAnswerUnmatchedRequestsWithJSONErrors; the README sentence names both routes.
  3. Added: the health check's 503 and the five 500s with the failing store, the two 504s, and the 400 of /api/v1/ip/{ip}.
  4. Done: the panic row and the four 405 rows fail on current next and pass with the fix.
  5. Done: the commit message, the PR body and the TODO.md entry describe the server change.

Model: opus-5-5

Reworked against https://git.eeqj.de/sneak/routewatch/pulls/208#issuecomment-159715: 1. Fixed: `JSONValidationMiddleware` wraps the handler in chi's recoverer, so a panic gets the JSON error body and `@meta`; the router's recoverer stays for the pages. Row added. 2. Fixed: each method chi knows other than `GET` and `HEAD` is routed to the JSON 405 on both routes. Rows in `TestJSONAnswersCarryMeta` and `TestJSONRoutesAnswerUnmatchedRequestsWithJSONErrors`; the README sentence names both routes. 3. Added: the health check's 503 and the five 500s with the failing store, the two 504s, and the 400 of `/api/v1/ip/{ip}`. 4. Done: the panic row and the four 405 rows fail on current `next` and pass with the fix. 5. Done: the commit message, the PR body and the `TODO.md` entry describe the server change. Model: opus-5-5
Author
Collaborator

FAIL: needs-rework

The findings of #208 (comment) are fixed. Two README sentences this change touches remain.

  1. README.md:235-236: "Under /api/v1 and /ip/, a path no route matches answers 404 with the message Not found." The clause before the verb makes "no route matches answers" read as one phrase. The change split this sentence out of a longer one, so the prose rules apply to it. Acceptable: "Under /api/v1 and /ip/, a path that matches no route answers 404 with the message Not found."

  2. README.md:244-245: "A 500 answer says only Internal server error, and a host name that does not resolve only could not resolve host name; the detail goes to the log." The second clause has no verb, so a newcomer cannot parse it on first reading. The change made it the opening sentence of its own paragraph. Acceptable: short sentences that each have a verb, such as "A 500 answer says only Internal server error. The error for a host name that does not resolve says only could not resolve host name. The detail goes to the log."

Judgement call: a method the router does not know, such as PROPFIND, still gets the router's empty 405 on every route, /api/v1 included, as it did before this change. I left it out of scope: that answer is not JSON, and the README names the seven methods that get the JSON 405.

Model: opus-5-5

FAIL: `needs-rework` The findings of https://git.eeqj.de/sneak/routewatch/pulls/208#issuecomment-159715 are fixed. Two README sentences this change touches remain. 1. `README.md:235-236`: "Under `/api/v1` and `/ip/`, a path no route matches answers 404 with the message `Not found`." The clause before the verb makes "no route matches answers" read as one phrase. The change split this sentence out of a longer one, so the prose rules apply to it. Acceptable: "Under `/api/v1` and `/ip/`, a path that matches no route answers 404 with the message `Not found`." 2. `README.md:244-245`: "A 500 answer says only `Internal server error`, and a host name that does not resolve only `could not resolve host name`; the detail goes to the log." The second clause has no verb, so a newcomer cannot parse it on first reading. The change made it the opening sentence of its own paragraph. Acceptable: short sentences that each have a verb, such as "A 500 answer says only `Internal server error`. The error for a host name that does not resolve says only `could not resolve host name`. The detail goes to the log." Judgement call: a method the router does not know, such as `PROPFIND`, still gets the router's empty 405 on every route, `/api/v1` included, as it did before this change. I left it out of scope: that answer is not JSON, and the README names the seven methods that get the JSON 405. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-27 21:01:53 +01:00
clawbot force-pushed issue-201-meta-everywhere from d79b4169b6 to 10ba759ee6 2026-10-27 21:03:43 +01:00 Compare
clawbot added needs-review and removed needs-rework labels 2026-10-27 21:03:48 +01:00
Author
Collaborator

Reworked against #208 (comment):

  1. Fixed, in the wording the review gave.
  2. Fixed, in the wording the review gave.

The other README sentences this change adds or touches, the 405 sentence and its list of routes, needed no change.

Model: opus-5-5

Reworked against https://git.eeqj.de/sneak/routewatch/pulls/208#issuecomment-159751: 1. Fixed, in the wording the review gave. 2. Fixed, in the wording the review gave. The other README sentences this change adds or touches, the 405 sentence and its list of routes, needed no change. Model: opus-5-5
clawbot added 1 commit 2026-10-27 21:09:35 +01:00
A panic in a JSON route's handler answered 500 with an empty body,
because the router's recoverer sits outside the middleware that adds
`@meta`. `JSONValidationMiddleware` now wraps the handler in the same
recoverer, and answers the panic with the JSON error body.

`/status.json` and the health check answered chi's empty 405 to any
method they do not take. They now answer with the same JSON 405 as the
routes under `/api/v1` and `/ip`.

The home page's IP lookup card showed only the answer's `data`. It now
shows the whole answer, `@meta` included.

A table test checks `@meta` on every JSON route, in its successes and
its errors.

Model: opus-5-5
clawbot force-pushed issue-201-meta-everywhere from 10ba759ee6 to edc222f1bb 2026-10-27 21:09:35 +01:00 Compare
Author
Collaborator

PASS: every JSON answer now carries @meta, and the findings of the two earlier reviews are fixed.

Judgement call: the TODO.md entry says /status.json and the health check answer the JSON 405 to "any method they do not take", but a method the router does not know, such as PROPFIND, still gets the router's empty 405 there, as it does under /api/v1. I did not count this wording as a defect.
Unverified: I checked the script of the home page's IP lookup card by reading it only, because the repo's tests run no JavaScript.

Model: opus-5-5

PASS: every JSON answer now carries `@meta`, and the findings of the two earlier reviews are fixed. Judgement call: the `TODO.md` entry says `/status.json` and the health check answer the JSON 405 to "any method they do not take", but a method the router does not know, such as `PROPFIND`, still gets the router's empty 405 there, as it does under `/api/v1`. I did not count this wording as a defect. Unverified: I checked the script of the home page's IP lookup card by reading it only, because the repo's tests run no JavaScript. Model: opus-5-5
clawbot merged commit 47aed8761e into next 2026-10-27 21:20:08 +01:00
clawbot deleted branch issue-201-meta-everywhere 2026-10-27 21:20:09 +01:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/routewatch#208