Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions packages/bun-uws/src/HttpContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -820,10 +820,6 @@ struct HttpContext {

auto *httpContextData = getSocketContextDataS(s);


if (httpResponseData->isConnectRequest && httpResponseData->socketData && httpContextData->onSocketDrain) {
httpContextData->onSocketDrain(httpResponseData->socketData, SSL, (struct us_socket_t *) s);
}
/* Ask the developer to write data and return success (true) or failure (false), OR skip sending anything and return success (true). */
if (httpResponseData->onWritable) {
/* We are now writable, so hang timeout again, the user does not have to do anything so we should hang until end or tryEnd rearms timeout */
Expand Down Expand Up @@ -862,6 +858,15 @@ struct HttpContext {
/* Drain any socket buffer, this might empty our backpressure and thus finish the request */
asyncSocket->flush();

/* node:http compat: a tunnel's own writes go out once the responses ahead owe nothing more. */
if constexpr (IsNodeHttp) {
bool tunnel = httpResponseData->isConnectRequest || (httpResponseData->state & HttpResponseData<SSL>::HTTP_NODE_TUNNEL_AFTER_BODY);
if (tunnel && httpResponseData->socketData && httpContextData->onSocketDrain
&& httpResponseData->onWritable == nullptr && asyncSocket->getBufferedAmount() == 0) {
httpContextData->onSocketDrain(httpResponseData->socketData, SSL, (struct us_socket_t *) s);
}
}
Comment thread
robobun marked this conversation as resolved.

/* node:http compat: reads were paused while pipelined responses were
* queued and stayed paused because the socket still had outgoing
* backpressure when the queue drained; now that it has flushed, read
Expand Down
4 changes: 4 additions & 0 deletions packages/bun-uws/src/HttpResponseData.h
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,10 @@ struct HttpResponseData : AsyncSocketData<SSL>, HttpParser {
/* Whether the connection should be torn down once the in-flight response (if
* any) has completed and all buffered outgoing data has been flushed. */
bool shouldCloseConnection() const {
/* node:http: a tunnel queued behind this response ends the connection itself, after its parked bytes. */
if ((isConnectRequest || (state & HTTP_NODE_TUNNEL_AFTER_BODY)) && nodeHttpQueuedPipelinedCount > 0) {
return false;
}
return (state & HTTP_CONNECTION_CLOSE)
|| ((state & HTTP_NODE_RECEIVED_FIN) && nodeHttpQueuedPipelinedCount == 0)
|| ((state & HTTP_CLOSE_WHEN_IDLE) && this->isIdle);
Expand Down
3 changes: 3 additions & 0 deletions src/js/internal/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ const kPendingCallbacks = Symbol("pendingCallbacks");
const kRequest = Symbol("request");
// Set on a server socket at the 'connect'/'upgrade' handoff: the native response of that request.
const kHandoffResponse = Symbol("kHandoffResponse");
// Server socket method: run a callback once the 'connect'/'upgrade' hand-off owns the connection.
const kOnHandoffActive = Symbol("kOnHandoffActive");
const kCloseCallback = Symbol("closeCallback");

// node:_http_server registers its pipelined-response machinery here at module
Expand Down Expand Up @@ -526,6 +528,7 @@ export {
kHandoffResponse,
kInternalSocketData,
kNeedDrain,
kOnHandoffActive,
kOutHeaders,
kPendingCallbacks,
kPerRequestCheckServerIdentity,
Expand Down
Loading
Loading