diff --git a/proxygen/lib/http/coro/HTTPStreamSource.cpp b/proxygen/lib/http/coro/HTTPStreamSource.cpp index 75baab326..a8681b343 100644 --- a/proxygen/lib/http/coro/HTTPStreamSource.cpp +++ b/proxygen/lib/http/coro/HTTPStreamSource.cpp @@ -267,7 +267,7 @@ folly::coro::Task HTTPStreamSource::readBodyEvent(uint32_t max) { // the queue. If this happens, EOM must be false. BufQueue bodyBuf(std::move(res.event.body)); res.event.body = bodyBuf.splitAtMost(max); - bodyQueue_.emplace_front(bodyBuf.move(), res.eom); + bodyQueue_.emplace_front(std::move(bodyBuf), res.eom); res.eom = false; length = max; } diff --git a/proxygen/lib/http/coro/test/HTTPSourceTests.cpp b/proxygen/lib/http/coro/test/HTTPSourceTests.cpp index 33d744508..7166ce238 100644 --- a/proxygen/lib/http/coro/test/HTTPSourceTests.cpp +++ b/proxygen/lib/http/coro/test/HTTPSourceTests.cpp @@ -224,6 +224,28 @@ TEST_F(HTTPStreamSourceTest, Body) { EXPECT_EQ(bodyEvents_[4].eom, true); } +// A body event larger than the read limit is split, and the rest goes back to +// the front of the queue with its length. +TEST_F(HTTPStreamSourceTest, SplitBodyKeepsTheRemainderLength) { + auto resp = std::make_unique(); + resp->setStatusCode(200); + stream_.headers(std::move(resp)); + stream_.body(BufQueue(folly::IOBuf::copyBuffer("abcdef")), 0); + stream_.eom(); + + co_withExecutor(&evb_, drainSource(&stream_, 4)).start(); + evb_.loopOnce(); + + EXPECT_FALSE(error_.hasValue()); + ASSERT_GE(bodyEvents_.size(), 2); + EXPECT_EQ(bodyEvents_[0].event.body.chainLength(), 4); + EXPECT_FALSE(bodyEvents_[0].eom); + EXPECT_EQ(bodyEvents_[1].event.body.chainLength(), 2); + auto rest = bodyEvents_[1].event.body.move(); + rest->coalesce(); + EXPECT_EQ(rest->moveToFbString(), std::string("ef")); +} + TEST_F(HTTPStreamSourceTest, PushPromiseBeforeResponseHeaders) { auto promiseSource = HTTPFixedSource::makeFixedResponse( 200, folly::IOBuf::copyBuffer("push body"));