Commit e9a211ed authored by jan.koester's avatar jan.koester
Browse files

test

parent 3a9ca3dc
Loading
Loading
Loading
Loading
+54 −2
Original line number Diff line number Diff line
@@ -1129,9 +1129,7 @@ namespace blogi {
                    return true;
                }

                // Store streaming state per-request
                req.RecvData.pos = 0;
                _storeStreamState(req, std::move(streamClient), sendSize, tid);

                libhttppp::HttpResponse curres;
                // Set content type based on requested format
@@ -1161,6 +1159,60 @@ namespace blogi {
                }

                curres.setContentLength(sendSize);

                // HTTP/1.x has no equivalent of H2's _resumeH2Streams (the
                // WINDOW_UPDATE-driven self-resumption libhttppp uses to keep
                // calling ResponseEvent for a deferred/streaming response) --
                // see proxyplus's HttpProxyServer.cpp Range branch for the
                // same distinction. Deferring via _storeStreamState() here and
                // returning would leave the stream permanently un-drained on
                // H1: nothing ever calls Response() again, and it just sits
                // until the STREAM_IDLE_TIMEOUT reaper discards it 30s later
                // with zero bytes sent (confirmed live via [STREAM-DIAG]).
                // H1 offload already runs this Controller() call on its own
                // dedicated blocking worker thread (see libhttppp's
                // _dispatchH1Request), so draining the whole body
                // synchronously right here is exactly as safe as proxyplus's
                // identical H1 fallback.
                bool isH1 = req.getRequestVersion().rfind("HTTP/1", 0) == 0;
                if (isH1) {
                    curres.send(req, "", -1);
                    if (!req.flushSendData()) {
                        streamClient.discard();
                        return true;
                    }
                    char chunk[65536];
                    size_t produced = 0;
                    bool deliveryOk = true;
                    while (produced < sendSize) {
                        const size_t remaining = sendSize - produced;
                        const size_t toRead = remaining < sizeof(chunk) ? remaining : sizeof(chunk);
                        size_t n;
                        try {
                            n = streamClient->readBodyChunk(chunk, toRead);
                        } catch (std::exception &e) {
                            std::cerr << "media: H1 stream failed after " << produced << "/"
                                      << sendSize << " bytes: " << e.what() << std::endl;
                            deliveryOk = false;
                            break;
                        }
                        if (n == 0) break;
                        req.SendData.append(chunk, n);
                        produced += n;
                        if (!req.flushSendData()) { deliveryOk = false; break; }
                    }
                    // Only let the connection go back to the pool if the body was fully
                    // drained -- an early break (upstream error, client gave up) leaves this
                    // HttpClient's read state unknown, same reasoning as every other
                    // discard() call site in this file.
                    if (!deliveryOk || produced < sendSize) {
                        streamClient.discard();
                    }
                    return true;
                }

                // Store streaming state per-request
                _storeStreamState(req, std::move(streamClient), sendSize, tid);
                curres.send(req, "", -1);
                return true;
            }