@@ -141,7 +141,7 @@ int HttpMessage::on_header_value(http_parser *parser,
141141}
142142
143143int HttpMessage::on_headers_complete (http_parser *parser) {
144- HttpMessage * http_message = (HttpMessage *)parser->data ;
144+ HttpMessage* http_message = (HttpMessage *)parser->data ;
145145 http_message->_stage = HTTP_ON_HEADERS_COMPLETE ;
146146 if (parser->http_major > 1 ) {
147147 // NOTE: this checking is a MUST because ProcessHttpResponse relies
@@ -282,9 +282,12 @@ int HttpMessage::OnBody(const char *at, const size_t length) {
282282 }
283283 if (!_read_body_progressively) {
284284 // Normal read.
285- // TODO: The input data is from IOBuf as well, possible to append
286- // data w/o copying.
287- _body.append (at, length);
285+ if (NULL != _current_source_iobuf) {
286+ _current_source_iobuf->append_to (
287+ &_body, length, _parsed_block_size + (at - _current_block_base));
288+ } else {
289+ _body.append (at, length);
290+ }
288291 return 0 ;
289292 }
290293 // Progressive read.
@@ -434,13 +437,8 @@ const http_parser_settings g_parser_settings = {
434437
435438HttpMessage::HttpMessage (bool read_body_progressively,
436439 HttpMethod request_method)
437- : _parsed_length(0 )
438- , _stage(HTTP_ON_MESSAGE_BEGIN )
439- , _request_method(request_method)
440- , _read_body_progressively(read_body_progressively)
441- , _body_reader(NULL )
442- , _cur_value(NULL )
443- , _vbodylen(0 ) {
440+ : _request_method(request_method)
441+ , _read_body_progressively(read_body_progressively) {
444442 http_parser_init (&_parser, HTTP_BOTH );
445443 _parser.allow_chunked_length = 1 ;
446444 _parser.data = this ;
@@ -489,15 +487,23 @@ ssize_t HttpMessage::ParseFromIOBuf(const butil::IOBuf &buf) {
489487 << " ) to already-completed message" ;
490488 return -1 ;
491489 }
490+ _parsed_block_size = 0 ;
491+ _current_source_iobuf = &buf;
492+ BRPC_SCOPE_EXIT {
493+ _current_source_iobuf = NULL ;
494+ };
492495 size_t nprocessed = 0 ;
493496 for (size_t i = 0 ; i < buf.backing_block_num (); ++i) {
494497 butil::StringPiece blk = buf.backing_block (i);
495498 if (blk.empty ()) {
496499 // length=0 will be treated as EOF by http_parser, must skip.
497500 continue ;
498501 }
499- nprocessed += http_parser_execute (
502+ _current_block_base = blk.data ();
503+ size_t n = http_parser_execute (
500504 &_parser, &g_parser_settings, blk.data (), blk.size ());
505+ nprocessed += n;
506+ _parsed_block_size += n;
501507 if (_parser.http_errno != 0 ) {
502508 // May try HTTP on other formats, failure is norm.
503509 RPC_VLOG << " Fail to parse http message, parser=" << _parser
0 commit comments