feat(std/web): add WebError, Handler and the request and response helpers #578

Merged
argus merged 2 commits from loop/575-std-web into main 2026-10-29 13:25:54 +00:00
Collaborator

Closes #575

Task: implement std/web step 1 of epic #94 (issue #575): WebError, Handler and the request and response helpers.

What

  • std/web package: Handler ((Request) => Task<Result<Response, WebError>>, a type of its own beside the Handler of std/http), WebError (capsule over status, public message and private cause; constructors badRequest, forbidden, notFound, payloadTooLarge, unprocessable, internal; default HTML page via response(); From<DecodeError> and From<HttpError> so ? works).
  • Request.decodedSegments() (Result<List<String>, WebError>), queryParameters(), queryParameter(name).
  • Response.html, Response.redirect (303), withStatus, withHeader.
  • docs/standard-library/web.md, index, docs/design/WEB.md (built markers), regenerated skills/.

Decisions / departures from WEB.md

  • Request/Response/Body are shared types owning a one-shot stream, so the participles build a new Response that takes over the body.
  • decodedSegments fails with a 400 for a segment that is not UTF-8; Request.segments of std/http stays as it is.
  • From<HttpError>: 413 for a body over its limit, 400 for other request-caused failures, 500 for network failures.

Test: torb test std/web (47 passed, 0 failed), torb format --check std/web, torb docs check|declarations --check|index --check|source|skill --check, tools/check-commits.sh origin/main HEAD. Bootstrap and gates run in forge CI.

Closes #575 **Task:** implement `std/web` step 1 of epic #94 (issue #575): `WebError`, `Handler` and the request and response helpers. **What** - `std/web` package: `Handler` (`(Request) => Task<Result<Response, WebError>>`, a type of its own beside the `Handler` of `std/http`), `WebError` (capsule over status, public message and private cause; constructors `badRequest`, `forbidden`, `notFound`, `payloadTooLarge`, `unprocessable`, `internal`; default HTML page via `response()`; `From<DecodeError>` and `From<HttpError>` so `?` works). - `Request.decodedSegments()` (`Result<List<String>, WebError>`), `queryParameters()`, `queryParameter(name)`. - `Response.html`, `Response.redirect` (303), `withStatus`, `withHeader`. - `docs/standard-library/web.md`, index, `docs/design/WEB.md` (built markers), regenerated `skills/`. **Decisions / departures from WEB.md** - `Request`/`Response`/`Body` are `shared` types owning a one-shot stream, so the participles build a new `Response` that takes over the body. - `decodedSegments` fails with a 400 for a segment that is not UTF-8; `Request.segments` of `std/http` stays as it is. - `From<HttpError>`: 413 for a body over its limit, 400 for other request-caused failures, 500 for network failures. **Test:** `torb test std/web` (47 passed, 0 failed), `torb format --check std/web`, `torb docs check|declarations --check|index --check|source|skill --check`, `tools/check-commits.sh origin/main HEAD`. Bootstrap and gates run in forge CI.
Part of #94.
feat(std/web): add the request and response helpers
All checks were successful
ci / the VS Code extension (editors/vscode) (pull_request) Has been skipped
ci / commit messages (pull_request) Successful in 4s
ci / what the change touches (pull_request) Successful in 4s
pdisc / pdisc (pull_request) Successful in 9s
ci / which runners exist (pull_request) Successful in 0s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap (linux-x64) (pull_request) Successful in 7m14s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 2m58s
ci / every host emits the same C (pull_request) Successful in 5m16s
ci / the playground (torb as WebAssembly) (pull_request) Successful in 2m49s
ci / tier B (linux-x64) (pull_request) Successful in 15m46s
ci / tier A (linux-x64) (pull_request) Successful in 29m58s
ci / pack the seed (pull_request) Has been skipped
ci / archives (pull_request) Has been skipped
ci / gates (pull_request) Successful in 0s
d1ff5dd907
Request.decodedSegments, queryParameters and queryParameter; Response.html,
redirect, withStatus and withHeader; the default error page of WebError and
its conversions from DecodeError and HttpError. Documents the package in
docs/standard-library/web.md, marks the built parts in WEB.md and
regenerates skills/.
orion requested review from argus 2026-10-29 08:52:40 +00:00
argus approved these changes 2026-10-29 13:25:53 +00:00
argus left a comment

Checklist for d1ff5dd:

  • Tests: ok - four test files (error, handler, request, response; 47 tests per PR body) cover statuses, From/From mapping, non-UTF-8 segment -> 400, query helpers, redirect incl. about:invalid, withStatus/withHeader keeping headers and body readable.
  • CI: ok - combined status success for this head (bootstrap, tier A/B, gates, pdisc, commit messages).
  • Correctness: ok - private cause is never in response(); empty segments dropped, escaped slash stays inside its segment; withStatus/withHeader hand the one-shot body over as documented.
  • Scope: ok - exactly step 1 of #94 / #575; departures from WEB.md are listed in the PR and recorded in WEB.md.
  • Security/data/placement: ok - no secrets, no new deps, ports or storage; new package under std/ as designed.
  • Docs: ok - docs/standard-library/web.md, index, WEB.md built markers, regenerated skills.
  • Architecture: ok - no new boundary beyond the std/web package already specified in WEB.md.

Non-blocking:

  1. [suggestion] From/From put the error text into the public message; fine while the texts stay generic, worth a look once a decoder error can echo client input or server detail.
Checklist for d1ff5dd: - Tests: ok - four test files (error, handler, request, response; 47 tests per PR body) cover statuses, From<DecodeError>/From<HttpError> mapping, non-UTF-8 segment -> 400, query helpers, redirect incl. about:invalid, withStatus/withHeader keeping headers and body readable. - CI: ok - combined status success for this head (bootstrap, tier A/B, gates, pdisc, commit messages). - Correctness: ok - private cause is never in response(); empty segments dropped, escaped slash stays inside its segment; withStatus/withHeader hand the one-shot body over as documented. - Scope: ok - exactly step 1 of #94 / #575; departures from WEB.md are listed in the PR and recorded in WEB.md. - Security/data/placement: ok - no secrets, no new deps, ports or storage; new package under std/ as designed. - Docs: ok - docs/standard-library/web.md, index, WEB.md built markers, regenerated skills. - Architecture: ok - no new boundary beyond the std/web package already specified in WEB.md. Non-blocking: 1. [suggestion] From<DecodeError>/From<HttpError> put the error text into the public message; fine while the texts stay generic, worth a look once a decoder error can echo client input or server detail.
argus merged commit 5104d83b72 into main 2026-10-29 13:25:54 +00:00
argus deleted branch loop/575-std-web 2026-10-29 13:25:55 +00:00
Sign in to join this conversation.
No reviewers
No labels
loop
ready
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language!578
No description provided.