HttpResponse::write() appends to a buffer and puts nothing on the wire
(src/http_response.c:641); the call that commits headers and streams is
send() (src/http_response.c:997). Node (res.write), Swoole
($response->write) and Go (w.Write) stream under the first name, so a
handler ported from any of them holds the whole body in memory and delivers it
in one piece at end(). Both field reports behind the body-contract work
(YanGusik/laravel-spawn#50, #60) came from the API rather than from the
adapter's own code.
Four more names in the same class report something other than what they say.
sendable() answers one bool for four questions — closed, sealed by
sendFile(), detached, full (src/http_response.c:1341). README.md
documented it as a liveness check until #174, and that is the loop which
truncated the stream in #60. Both replacements are already in: isWritable()
for liveness (#176), tryWrite() and awaitWritable() for room (#178).
isClosed() returns response->closed, the flag end() sets
(src/http_response.c:1557). It reports nothing about the connection, so a
handler that reads it as "the peer is gone" gets a wrong answer for the whole
life of the response.
getBodyStream() returns null and setBodyStream() throws "not yet
implemented" (src/http_response.c:721,731). Neither has ever had an
implementation behind it.
The naming already cost a working call site inside this repository:
tests/perf/servers/server_stream.php:45 calls ->send() with no argument
(arginfo requires one, stubs/HttpResponse.php_arginfo.h:67) and streams its
chunks with ->write(), which buffers them. The stream profile of the perf
harness fails with ArgumentCountError before it measures anything.
Proposal
| Today |
After |
Behaviour |
send(string): static |
write(string): static |
streams; send() kept one minor as an alias |
write(string): static |
appendBody(string): static |
appends to the buffered body |
isClosed(): bool |
isEnded(): bool |
end() has been called |
sendable(): bool |
removed |
tombstone naming isWritable() and tryWrite() |
getBodyStream(): mixed |
removed |
never implemented |
setBodyStream(mixed): static |
removed |
never implemented |
send() carries no E_DEPRECATED: it is a per-chunk call, and PHP emits the
notice on every one of them.
Compatibility
Seven CHANGELOG entries. laravel-spawn is a two-line diff — Sse::connected()
calls isWritable() (done ahead of the rename in YanGusik/laravel-spawn#63,
#64), and send() becomes write().
The dangerous one is write(): a handler that used it for buffered appending
keeps compiling and starts streaming, which commits headers on the first call
and makes every later setHeader() throw. The CHANGELOG entry has to name it
first.
HttpResponse::write()appends to a buffer and puts nothing on the wire(
src/http_response.c:641); the call that commits headers and streams issend()(src/http_response.c:997). Node (res.write), Swoole(
$response->write) and Go (w.Write) stream under the first name, so ahandler ported from any of them holds the whole body in memory and delivers it
in one piece at
end(). Both field reports behind the body-contract work(YanGusik/laravel-spawn#50, #60) came from the API rather than from the
adapter's own code.
Four more names in the same class report something other than what they say.
sendable()answers one bool for four questions — closed, sealed bysendFile(), detached, full (src/http_response.c:1341).README.mddocumented it as a liveness check until #174, and that is the loop which
truncated the stream in #60. Both replacements are already in:
isWritable()for liveness (#176),
tryWrite()andawaitWritable()for room (#178).isClosed()returnsresponse->closed, the flagend()sets(
src/http_response.c:1557). It reports nothing about the connection, so ahandler that reads it as "the peer is gone" gets a wrong answer for the whole
life of the response.
getBodyStream()returns null andsetBodyStream()throws "not yetimplemented" (
src/http_response.c:721,731). Neither has ever had animplementation behind it.
The naming already cost a working call site inside this repository:
tests/perf/servers/server_stream.php:45calls->send()with no argument(arginfo requires one,
stubs/HttpResponse.php_arginfo.h:67) and streams itschunks with
->write(), which buffers them. The stream profile of the perfharness fails with ArgumentCountError before it measures anything.
Proposal
send(string): staticwrite(string): staticsend()kept one minor as an aliaswrite(string): staticappendBody(string): staticisClosed(): boolisEnded(): boolend()has been calledsendable(): boolisWritable()andtryWrite()getBodyStream(): mixedsetBodyStream(mixed): staticsend()carries noE_DEPRECATED: it is a per-chunk call, and PHP emits thenotice on every one of them.
Compatibility
Seven CHANGELOG entries. laravel-spawn is a two-line diff —
Sse::connected()calls
isWritable()(done ahead of the rename in YanGusik/laravel-spawn#63,#64), and
send()becomeswrite().The dangerous one is
write(): a handler that used it for buffered appendingkeeps compiling and starts streaming, which commits headers on the first call
and makes every later
setHeader()throw. The CHANGELOG entry has to name itfirst.