in proxygen/lib/http/codec/HQStreamCodec.cpp [205:266]
void HQStreamCodec::onHeadersComplete(HTTPHeaderSize decodedSize,
bool acknowledge) {
CHECK(parserPaused_);
decodeInfo_.onHeadersComplete(decodedSize);
auto resumeParser = folly::makeGuard([this] { setParserPaused(false); });
auto g2 = folly::makeGuard(activationHook_());
// Check parsing error
DCHECK_EQ(decodeInfo_.decodeError, HPACK::DecodeError::NONE);
// Leave msg in decodeInfo_ for now, to keep the parser paused
if (!decodeInfo_.parsingError.empty()) {
LOG(ERROR) << "Failed parsing header list for stream=" << streamId_
<< ", error=" << decodeInfo_.parsingError;
if (!decodeInfo_.headerErrorValue.empty()) {
std::cerr << " value=" << decodeInfo_.headerErrorValue << std::endl;
}
HTTPException err(
HTTPException::Direction::INGRESS,
fmt::format("HQStreamCodec stream error: stream={} status={} error:{}",
streamId_,
400,
decodeInfo_.parsingError));
if (parsingTrailers_) {
err.setHttp3ErrorCode(HTTP3::ErrorCode::HTTP_MESSAGE_ERROR);
} else {
err.setHttpStatusCode(400);
}
err.setProxygenError(kErrorParseHeader);
callback_->onError(streamId_, err, true);
resumeParser.dismiss();
return;
}
std::unique_ptr<HTTPMessage> msg = std::move(decodeInfo_.msg);
msg->setAdvancedProtocolString(getCodecProtocolString(CodecProtocol::HQ));
if (curHeader_.type == hq::FrameType::HEADERS) {
if (!finalIngressHeadersSeen_ &&
(msg->isRequest() || !msg->is1xxResponse())) {
finalIngressHeadersSeen_ = true;
}
}
if (transportDirection_ == TransportDirection::DOWNSTREAM &&
msg->getMethod() == HTTPMethod::CONNECT) {
isConnect_ = true;
}
if (acknowledge) {
qpackDecoderWriteBuf_.append(headerCodec_.encodeHeaderAck(streamId_));
}
// Report back what we've parsed
if (callback_) {
if (parsingTrailers_) {
auto trailerHeaders =
std::make_unique<HTTPHeaders>(msg->extractHeaders());
callback_->onTrailersComplete(streamId_, std::move(trailerHeaders));
} else {
// TODO: should we treat msg as chunked like H2?
callback_->onHeadersComplete(streamId_, std::move(msg));
}
}
}