summaryrefslogtreecommitdiffstats
path: root/net/http
diff options
context:
space:
mode:
Diffstat (limited to 'net/http')
-rw-r--r--net/http/http_request_headers.cc1
-rw-r--r--net/http/http_request_headers.h1
-rw-r--r--net/http/http_stream_parser.cc44
-rw-r--r--net/http/http_stream_parser.h5
-rw-r--r--net/http/http_util.cc11
5 files changed, 48 insertions, 14 deletions
diff --git a/net/http/http_request_headers.cc b/net/http/http_request_headers.cc
index 93ead01..9ce77bf 100644
--- a/net/http/http_request_headers.cc
+++ b/net/http/http_request_headers.cc
@@ -30,6 +30,7 @@ const char HttpRequestHeaders::kProxyConnection[] = "Proxy-Connection";
const char HttpRequestHeaders::kRange[] = "Range";
const char HttpRequestHeaders::kReferer[] = "Referer";
const char HttpRequestHeaders::kUserAgent[] = "User-Agent";
+const char HttpRequestHeaders::kTransferEncoding[] = "Transfer-Encoding";
HttpRequestHeaders::HeaderKeyValuePair::HeaderKeyValuePair() {
}
diff --git a/net/http/http_request_headers.h b/net/http/http_request_headers.h
index 2962ae2..ef4b60d 100644
--- a/net/http/http_request_headers.h
+++ b/net/http/http_request_headers.h
@@ -73,6 +73,7 @@ class HttpRequestHeaders {
static const char kRange[];
static const char kReferer[];
static const char kUserAgent[];
+ static const char kTransferEncoding[];
HttpRequestHeaders();
~HttpRequestHeaders();
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc
index 2a3fb15..2d00a26 100644
--- a/net/http/http_stream_parser.cc
+++ b/net/http/http_stream_parser.cc
@@ -43,7 +43,10 @@ HttpStreamParser::HttpStreamParser(ClientSocketHandle* connection,
DCHECK_EQ(0, read_buffer->offset());
}
-HttpStreamParser::~HttpStreamParser() {}
+HttpStreamParser::~HttpStreamParser() {
+ if (request_body_ != NULL && request_body_->is_chunked())
+ request_body_->set_chunk_callback(NULL);
+}
int HttpStreamParser::SendRequest(const std::string& request_line,
const HttpRequestHeaders& headers,
@@ -67,6 +70,8 @@ int HttpStreamParser::SendRequest(const std::string& request_line,
request_headers_ = new DrainableIOBuffer(headers_io_buf,
headers_io_buf->size());
request_body_.reset(request_body);
+ if (request_body_ != NULL && request_body_->is_chunked())
+ request_body_->set_chunk_callback(this);
io_state_ = STATE_SENDING_HEADERS;
int result = DoLoop(OK);
@@ -143,6 +148,16 @@ void HttpStreamParser::OnIOComplete(int result) {
}
}
+void HttpStreamParser::OnChunkAvailable() {
+ // This method may get called while sending the headers or body, so check
+ // before processing the new data. If we were still initializing or sending
+ // headers, we will automatically start reading the chunks once we get into
+ // STATE_SENDING_BODY so nothing to do here.
+ DCHECK(io_state_ == STATE_SENDING_HEADERS || io_state_ == STATE_SENDING_BODY);
+ if (io_state_ == STATE_SENDING_BODY)
+ OnIOComplete(0);
+}
+
int HttpStreamParser::DoLoop(int result) {
bool can_do_more = true;
do {
@@ -208,12 +223,16 @@ int HttpStreamParser::DoSendHeaders(int result) {
// We'll record the count of uncoalesced packets IFF coalescing will help,
// and otherwise we'll use an enum to tell why it won't help.
enum COALESCE_POTENTIAL {
- NO_ADVANTAGE = 0, // Coalescing won't reduce packet count.
- HEADER_ONLY = 1, // There is only a header packet (can't coalesce).
- COALESCE_POTENTIAL_MAX = 30 // Various cases of coalasced savings.
+ // Coalescing won't reduce packet count.
+ NO_ADVANTAGE = 0,
+ // There is only a header packet or we have a request body but the
+ // request body isn't available yet (can't coalesce).
+ HEADER_ONLY = 1,
+ // Various cases of coalasced savings.
+ COALESCE_POTENTIAL_MAX = 30
};
size_t coalesce = HEADER_ONLY;
- if (request_body_ != NULL) {
+ if (request_body_ != NULL && !request_body_->is_chunked()) {
const size_t kBytesPerPacket = 1430;
uint64 body_packets = (request_body_->size() + kBytesPerPacket - 1) /
kBytesPerPacket;
@@ -236,7 +255,8 @@ int HttpStreamParser::DoSendHeaders(int result) {
result = connection_->socket()->Write(request_headers_,
bytes_remaining,
&io_callback_);
- } else if (request_body_ != NULL && request_body_->size()) {
+ } else if (request_body_ != NULL &&
+ (request_body_->is_chunked() || request_body_->size())) {
io_state_ = STATE_SENDING_BODY;
result = OK;
} else {
@@ -246,13 +266,17 @@ int HttpStreamParser::DoSendHeaders(int result) {
}
int HttpStreamParser::DoSendBody(int result) {
- if (result > 0)
- request_body_->DidConsume(result);
+ request_body_->MarkConsumedAndFillBuffer(result);
if (!request_body_->eof()) {
int buf_len = static_cast<int>(request_body_->buf_len());
- result = connection_->socket()->Write(request_body_->buf(), buf_len,
- &io_callback_);
+ if (buf_len) {
+ result = connection_->socket()->Write(request_body_->buf(), buf_len,
+ &io_callback_);
+ } else {
+ // More POST data is to come hence wait for the callback.
+ result = ERR_IO_PENDING;
+ }
} else {
io_state_ = STATE_REQUEST_SENT;
}
diff --git a/net/http/http_stream_parser.h b/net/http/http_stream_parser.h
index bbd551f..5f7e943 100644
--- a/net/http/http_stream_parser.h
+++ b/net/http/http_stream_parser.h
@@ -26,7 +26,7 @@ class IOBuffer;
class SSLCertRequestInfo;
class SSLInfo;
-class HttpStreamParser {
+class HttpStreamParser : public ChunkCallback {
public:
// Any data in |read_buffer| will be used before reading from the socket
// and any data left over after parsing the stream will be put into
@@ -71,6 +71,9 @@ class HttpStreamParser {
void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info);
+ // ChunkCallback methods.
+ virtual void OnChunkAvailable();
+
private:
// FOO_COMPLETE states implement the second half of potentially asynchronous
// operations and don't necessarily mean that FOO is complete.
diff --git a/net/http/http_util.cc b/net/http/http_util.cc
index bf56136..0f28c83 100644
--- a/net/http/http_util.cc
+++ b/net/http/http_util.cc
@@ -674,9 +674,14 @@ void HttpUtil::BuildRequestHeaders(const HttpRequestInfo* request_info,
// Add a content length header?
if (upload_data_stream) {
- request_headers->SetHeader(
- HttpRequestHeaders::kContentLength,
- base::Uint64ToString(upload_data_stream->size()));
+ if (upload_data_stream->is_chunked()) {
+ request_headers->SetHeader(
+ HttpRequestHeaders::kTransferEncoding, "chunked");
+ } else {
+ request_headers->SetHeader(
+ HttpRequestHeaders::kContentLength,
+ base::Uint64ToString(upload_data_stream->size()));
+ }
} else if (request_info->method == "POST" || request_info->method == "PUT" ||
request_info->method == "HEAD") {
// An empty POST/PUT request still needs a content length. As for HEAD,