Skip to content
Merged
Changes from 1 commit
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
Next Next commit
Take content length into account when reading body
  • Loading branch information
joelreymont committed Oct 30, 2012
commit d00836dfe281a59af8dacbb6864fe0bcae2d39a0
55 changes: 45 additions & 10 deletions include/network/protocol/http/client/connection/async_normal.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -430,20 +430,53 @@ struct http_async_connection_pimpl : boost::enable_shared_from_this<http_async_c
placeholders::bytes_transferred)));
} else {
NETWORK_MESSAGE("no callback provided, appending to body...");
bool get_more = true;
buffer_type::const_iterator begin = this->part.begin();
buffer_type::const_iterator end = begin;
std::advance(end, bytes_transferred);
// check the content length header
//auto headers_future = headers_promise.get_future();
auto it = headers_.find("Content-Length");
if (it != headers_.end()) {
try {
unsigned content_length = stoi(it->second);
get_more = (end - begin) < content_length;
NETWORK_MESSAGE("Content-Length: " << content_length
<< ", disconnect: " << !get_more);
} catch(...) {
}
}
// Here we don't have a body callback. Let's
// make sure that we deal with the remainder
// from the headers part in case we do have data
// that's still in the buffer.
this->parse_body(request_strand_.wrap(
boost::bind(
&this_type::handle_received_data,
this_type::shared_from_this(),
body,
get_body,
callback,
placeholders::error,
placeholders::bytes_transferred)),
bytes_transferred);
if (get_more) {
this->parse_body(request_strand_.wrap(
boost::bind(
&this_type::handle_received_data,
this_type::shared_from_this(),
body,
get_body,
callback,
placeholders::error,
placeholders::bytes_transferred)),
bytes_transferred);
} else {
std::string body_string;
std::swap(body_string, this->partial_parsed);
body_string.append(
this->part.begin()
, bytes_transferred
);
this->body_promise.set_value(body_string);
// TODO set the destination value somewhere!
this->destination_promise.set_value("");
this->source_promise.set_value("");
this->part.assign('\0');
this->response_parser_.reset();
//NETWORK_MESSAGE("forcing socket disconnect on content length");
//connection_delegate_->disconnect();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You really don't need to force the disconnection. The connection can die a natural death.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about the block below // TODO? Is it really needed? I don't understand the meaning of source and destination here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The source of the message is technically the server from which the message originated from. I used to populate this (I think) with an IP address of the remote host. The destination I leave blank because technically the destination of the response is the current connection handling the request. In the future I may put something useful there, but in the meantime the destination is kept empty.

The assigning of an empty string is unnecessary, as default-constructed strings usually use small-string optimization and will hold 16 bytes (or some similar amount) of strings. Remove that as you don't really need to do it anyway.

}
}
}
return;
Expand Down Expand Up @@ -709,6 +742,7 @@ struct http_async_connection_pimpl : boost::enable_shared_from_this<http_async_c
boost::trim(header_pair.second);
headers.insert(header_pair);
}
this->headers_ = headers;
headers_promise.set_value(headers);
}

Expand Down Expand Up @@ -790,6 +824,7 @@ struct http_async_connection_pimpl : boost::enable_shared_from_this<http_async_c
boost::promise<boost::uint16_t> status_promise;
boost::promise<std::string> status_message_promise;
boost::promise<std::multimap<std::string, std::string> > headers_promise;
std::multimap<std::string, std::string> headers_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest doing this another way:

  • make an optional content length member.
  • only set the content length member if there was a header parsed for content-length.
  • make the determination on whether to continue if the total length of the body that's been parsed is already equal to the content-length.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, please review.

boost::promise<std::string> source_promise;
boost::promise<std::string> destination_promise;
boost::promise<std::string> body_promise;
Expand Down