Http.text and Http.header return copies - they handed back the handle's own buffer (and on macOS the response's string), which Http.free released: a text read before the free and used after it was garbage or empty (maroon-lake's maps.json was written with 0 bytes)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
aba5d9e679
commit
359de7bfe5
4 changed files with 19 additions and 4 deletions
6
changes/http-text-copy.md
Normal file
6
changes/http-text-copy.md
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
bump: patch
|
||||||
|
type: fix
|
||||||
|
**`Http.text` and `Http.header` return copies.** They handed back the handle's own buffer (and on macOS the
|
||||||
|
response object's string), which `Http.free` then released: a text read before the free and used after it
|
||||||
|
was garbage or empty - maroon-lake's map list wrote a 0-byte maps.json. Each call now returns a string that
|
||||||
|
is the caller's to keep. Read a body once per response.
|
||||||
|
|
@ -11,7 +11,7 @@ ns: Http
|
||||||
member: header
|
member: header
|
||||||
---
|
---
|
||||||
|
|
||||||
Returns a response header value by name (case-insensitive), or an empty result if absent.
|
Returns a response header value by name (case-insensitive), or an empty result if absent. The value is a copy, yours to keep after <code>Http.free</code>.
|
||||||
|
|
||||||
```ludic
|
```ludic
|
||||||
program Demo {
|
program Demo {
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ ns: Http
|
||||||
member: text
|
member: text
|
||||||
---
|
---
|
||||||
|
|
||||||
Returns the response body as a NUL-terminated string. Pair with <code>Json.parse</code> (#44) for JSON APIs.
|
Returns the response body as a NUL-terminated string: a copy that stays yours after <code>Http.free</code> lets the handle go, so read it once and keep what you read. Pair with <code>Json.parse</code> (#44) for JSON APIs.
|
||||||
|
|
||||||
```ludic
|
```ludic
|
||||||
program Demo {
|
program Demo {
|
||||||
|
|
|
||||||
|
|
@ -237,9 +237,13 @@ function http_ok(rt_http_st: mut RtHttpState, h: int) -> bool {
|
||||||
return (st >= 200) and (st < 300)
|
return (st >= 200) and (st < 300)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# the body as text: a COPY, the caller's to keep - the handle's own buffer goes with Http.free, and a
|
||||||
|
# text read before the free and used after it wrote an empty file (maroon-lake's maps.json)
|
||||||
function http_text(rt_http_st: mut RtHttpState, h: int) -> string {
|
function http_text(rt_http_st: mut RtHttpState, h: int) -> string {
|
||||||
if not http_valid(rt_http_st, h) { return null }
|
if not http_valid(rt_http_st, h) { return null }
|
||||||
return rt_http_st.h_body[h - 1]
|
let b = rt_http_st.h_body[h - 1]
|
||||||
|
if b == null { return null }
|
||||||
|
return http_slice_dup(b, 0, rt_http_st.h_blen[h - 1])
|
||||||
}
|
}
|
||||||
|
|
||||||
function http_body_len(rt_http_st: mut RtHttpState, h: int) -> int {
|
function http_body_len(rt_http_st: mut RtHttpState, h: int) -> int {
|
||||||
|
|
@ -250,7 +254,12 @@ function http_body_len(rt_http_st: mut RtHttpState, h: int) -> int {
|
||||||
function http_header_of(rt_http_st: mut RtHttpState, h: int, name: pointer) -> string {
|
function http_header_of(rt_http_st: mut RtHttpState, h: int, name: pointer) -> string {
|
||||||
if not http_valid(rt_http_st, h) { return null }
|
if not http_valid(rt_http_st, h) { return null }
|
||||||
let s = h - 1
|
let s = h - 1
|
||||||
if rt_http_st.h_native[s] == 1 { return hs_header(s, name) }
|
# a copy on both paths: the native value is the response's own, released with Http.free
|
||||||
|
if rt_http_st.h_native[s] == 1 {
|
||||||
|
let v = hs_header(s, name)
|
||||||
|
if v == null { return null }
|
||||||
|
return http_slice_dup(v, 0, http_cstr_len(v))
|
||||||
|
}
|
||||||
return http_find_header(rt_http_st.h_hdr[s], name)
|
return http_find_header(rt_http_st.h_hdr[s], name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue