Repository navigation
0.4.0
Spindle moves to wiretype 0.4.0 and rowtype 0.6.0, types statuses everywhere, holds route tables and cookies to stricter rules, and fixes WebSocket, client and server edge cases.
Upgrading
Dependencies
spindleneeds wiretype 0.4.0;spindle_postgresneeds rowtype 0.6.0 and postgres-eio 0.4.0.- A
DEFERRABLEconstraint that refusesCOMMITis`Conflictwith its name, was`Not_committedand a500. Rowtype_postgres.Conninfo.tis private: useConninfo.with_databaseandConninfo.with_connect_timeout.- OpenAPI and Zod write a parameterised type where it is used, not as a shared component, unless
[@@kind]names it.
Route tables
App.makerefuses a JSON answer under204or205: useReturns.emptyorReturns.empty_response.App.makerefusesReturns.json ~statusorReturns.empty ~statusoutside2xx; a redirect isReturns.responsewithResponse.redirect.App.makerefuses aRefusal.Codewhose status is not4xxor5xx.
Statuses
Spindle_client'sstatusis aSpindle_http.Status.t, was anint: match`OKor useStatus.to_int.Spindle.Test.response'sstatusis aSpindle_http.Status.ttoo: match`OKor compareStatus.to_int r.status.Head.Response.readanswersHead.Response.error(Closed,Malformed of string), was`Closed/`Malformed.- A Structured Field date is
Structured.Date of Ptime.t, was anintof seconds; years outside 0–9999 are refused.
Client errors
Spindle_client.errorsays whether the request went out:Unreachable→Unsent(never left) orUnanswered(sent, not answered whole).- Treat
TimeoutasUnanswered; a client span's failure saysunsentorunanswered.
Cookies, keys and forms
Cookie.signed/Cookie.encrypted:~max_age_s:86400→~max_age:Mtime.Span.(1 * day), a span.Cookie.make ?max_age_sstays seconds.Key.signandKey.sealuse their own derived keys: tokens made before no longer verify or open. Cookies are unaffected.Form.file,Form.file_opt,Form.files→Form.File.required,Form.File.optional,Form.File.list, each aForm.File.t.
CORS
- Under
Cors.Any, a cross-site write carryingAuthorization: Basic,Digest,NegotiateorNTLMis403 cross_origin, as aCookieis.Bearerworks as before.
New
Spindle_clientconnects through thenetit is given, so a test can passEio_mock.Net.- A raising WebSocket handler is logged once at
error, with what was raised and where; a client's line says where it went and how long it lived.
Fixed
- A peer reading a large WebSocket message slowly is no longer cut off:
send_timeoutruns from the last byte it took. - A WebSocket message's buffer grows as bytes arrive; fourteen bytes could hold
max_messageof memory. Spindle_clientsends a URL's path and query as written:%3B,%2Fand+are kept, so signed URLs stay valid.- A JSON map key read in more than one spelling is refused when given twice.
- Kinds that refer to each other in a ring of three or more are written as references, not as any JSON.
Rate.createraisesInvalid_argumentfor apershorter thanlimitnanoseconds, which limited nothing.Refusal.busywrites aRetry-Afterof at least one second.Expect: 100-continueamong other elements, or in a second field, gets100 Continue.- A failed
accept(out of descriptors, reset) is logged and retried after 10 ms, where it stopped the server. Response.streamsends from several fibers one after another, andsend_timeoutends each.Path.urlwrites a.or..segment as%2Eor%2E%2E.- A client connection that fails to connect leaves no socket behind.