tur/httpd-string
optional owned-String accessors for stdlib/httpd.
The httpd-req-cookie / httpd-req-form accessors return a cstr that is a fresh malloc on the HIT path but a static "" literal on the MISS path (the header/field is absent). That sentinel mixing makes the blind string/adopt-cstr recipe unsafe here: adopting the miss-path literal would free() static storage (undefined behavior), and the "" sentinel cannot distinguish "present and empty" from "absent" at all.
This opt-in module layers the honest type on top: option<String>. Each *-opt is a thin Turmeric wrapper over an inline-C *-raw helper that returns a freshly-malloc'd cstr on a match and a NULL pointer on any miss (never a static literal). The wrapper maps NULL -> none and adopts the fresh buffer into some -- so there is no static-literal free, and "present but empty" is a distinct some "" (a fresh empty buffer) from "absent" (none). Because the Option is constructed in Turmeric with real some/none, it is an ordinary by-value (Option String) that composes anywhere (let-bind it, pass it, option-map it) -- consume it with some? / unwrap / unwrap-or.
It is ADDITIVE: the cstr accessors in stdlib/httpd stay for callers that want the borrow-and-immediately-use path. It is a SEPARATE module so the httpd core does not pull stdlib/string (map/typeclass) into every server's load graph -- only programs that want owned cookie/form Strings load this.
Note: the *-raw helpers have inline-C bodies (they reuse httpd's request-parsing walk), so like stdlib/httpd itself they run on the compiled path.
Since: v2 (string-owned-builders-and-optional-accessors-plan, Part 2)
httpd-req-cookie-raw
(httpd-req-cookie-raw [conn :ptr<void> name :cstr] :cstr)
internal: cookie value as a fresh cstr, or NULL.
Same Cookie-header walk as httpd-req-cookie, but returns NULL (not "") on every miss and a freshly-malloc'd buffer on a match (an empty match yields a fresh 1-byte ""), so the caller can tell absent from present-empty and adopt the buffer without ever freeing a static literal.
httpd-req-cookie-opt
(httpd-req-cookie-opt [conn :ptr<void> name :cstr] :(Option String))
read a cookie value as an optional owned String.
Parses the request's Cookie: header into name=value pairs and returns the value for name as some owned String, or none if the arguments are bad, the header is absent, or the cookie is not present. Unlike the cstr form (httpd-req-cookie, which returns "" for both absent and present-empty), a present cookie with an empty value is some "", distinct from none.
| conn | connection handle from the worker | |
| name | cookie name to look up (case-sensitive, per RFC 6265) |
(Option String) -- some owned value on a match, none on any miss.
(let [o (httpd-req-cookie-opt c "session")] (if (some? o) (string/to-cstr (unwrap o)) "<no session>"))
Since: v2
httpd-req-form-raw
(httpd-req-form-raw [conn :ptr<void> field :cstr] :cstr)
internal: decoded form value as a fresh cstr, or NULL.
Same body walk + percent/plus decode as httpd-req-form, but returns NULL (not "") on every miss and a freshly-malloc'd decoded buffer on a match, so the caller can tell absent from present-empty and adopt without freeing a literal.
httpd-req-form-opt
(httpd-req-form-opt [conn :ptr<void> field :cstr] :(Option String))
look up a URL-encoded form field as an optional String.
Walks the (already-received) request body for name=value separated by &, percent-decoding the value and mapping + to space per the application/x-www-form-urlencoded convention. Returns some owned String on a match, or none when the arguments are bad, the body is empty, or the field is absent. A present field with an empty value is some "", distinct from none (which the cstr form httpd-req-form cannot express).
| conn | connection handle from the worker | |
| field | form field name (case-sensitive, plain ASCII) |
(Option String) -- some decoded owned value on a match, none on any miss.
(let [o (httpd-req-form-opt c "username")] (if (some? o) (string/to-cstr (unwrap o)) "<anonymous>"))
Since: v2
cstr-null?
(cstr-null? [s :cstr] :bool)
internal: true iff the cstr pointer is NULL (a miss sentinel).