| Index: net/http/http_network_transaction.cc
|
| ===================================================================
|
| --- net/http/http_network_transaction.cc (revision 14682)
|
| +++ net/http/http_network_transaction.cc (working copy)
|
| @@ -31,6 +31,10 @@
|
|
|
| namespace net {
|
|
|
| +void HttpNetworkTransaction::ResponseHeaders::Realloc(size_t new_size) {
|
| + headers_.reset(static_cast<char*>(realloc(headers_.release(), new_size)));
|
| +}
|
| +
|
| //-----------------------------------------------------------------------------
|
|
|
| HttpNetworkTransaction::HttpNetworkTransaction(HttpNetworkSession* session,
|
| @@ -50,7 +54,9 @@
|
| using_tunnel_(false),
|
| establishing_tunnel_(false),
|
| reading_body_from_socket_(false),
|
| + request_headers_(new RequestHeaders()),
|
| request_headers_bytes_sent_(0),
|
| + header_buf_(new ResponseHeaders()),
|
| header_buf_capacity_(0),
|
| header_buf_len_(0),
|
| header_buf_body_offset_(-1),
|
| @@ -298,29 +304,31 @@
|
| HttpUtil::SpecForRequest(request_->url) :
|
| HttpUtil::PathForRequest(request_->url);
|
|
|
| - request_headers_ = request_->method + " " + path +
|
| + request_headers_->headers_ = request_->method + " " + path +
|
| " HTTP/1.1\r\nHost: " + request_->url.host();
|
| if (request_->url.IntPort() != -1)
|
| - request_headers_ += ":" + request_->url.port();
|
| - request_headers_ += "\r\n";
|
| + request_headers_->headers_ += ":" + request_->url.port();
|
| + request_headers_->headers_ += "\r\n";
|
|
|
| // For compat with HTTP/1.0 servers and proxies:
|
| if (using_proxy_)
|
| - request_headers_ += "Proxy-";
|
| - request_headers_ += "Connection: keep-alive\r\n";
|
| + request_headers_->headers_ += "Proxy-";
|
| + request_headers_->headers_ += "Connection: keep-alive\r\n";
|
|
|
| if (!request_->user_agent.empty())
|
| - request_headers_ += "User-Agent: " + request_->user_agent + "\r\n";
|
| + request_headers_->headers_ += "User-Agent: " + request_->user_agent +
|
| + "\r\n";
|
|
|
| // Our consumer should have made sure that this is a safe referrer. See for
|
| // instance WebCore::FrameLoader::HideReferrer.
|
| if (request_->referrer.is_valid())
|
| - request_headers_ += "Referer: " + request_->referrer.spec() + "\r\n";
|
| + request_headers_->headers_ += "Referer: " + request_->referrer.spec() +
|
| + "\r\n";
|
|
|
| // Add a content length header?
|
| if (request_->upload_data) {
|
| request_body_stream_.reset(new UploadDataStream(request_->upload_data));
|
| - request_headers_ +=
|
| + request_headers_->headers_ +=
|
| "Content-Length: " + Uint64ToString(request_body_stream_->size()) +
|
| "\r\n";
|
| } else if (request_->method == "POST" || request_->method == "PUT" ||
|
| @@ -329,22 +337,23 @@
|
| // IE and Safari also add a content length header. Presumably it is to
|
| // support sending a HEAD request to an URL that only expects to be sent a
|
| // POST or some other method that normally would have a message body.
|
| - request_headers_ += "Content-Length: 0\r\n";
|
| + request_headers_->headers_ += "Content-Length: 0\r\n";
|
| }
|
|
|
| // Honor load flags that impact proxy caches.
|
| if (request_->load_flags & LOAD_BYPASS_CACHE) {
|
| - request_headers_ += "Pragma: no-cache\r\nCache-Control: no-cache\r\n";
|
| + request_headers_->headers_ +=
|
| + "Pragma: no-cache\r\nCache-Control: no-cache\r\n";
|
| } else if (request_->load_flags & LOAD_VALIDATE_CACHE) {
|
| - request_headers_ += "Cache-Control: max-age=0\r\n";
|
| + request_headers_->headers_ += "Cache-Control: max-age=0\r\n";
|
| }
|
|
|
| ApplyAuth();
|
|
|
| // TODO(darin): Need to prune out duplicate headers.
|
|
|
| - request_headers_ += request_->extra_headers;
|
| - request_headers_ += "\r\n";
|
| + request_headers_->headers_ += request_->extra_headers;
|
| + request_headers_->headers_ += "\r\n";
|
| }
|
|
|
| // The HTTP CONNECT method for establishing a tunnel connection is documented
|
| @@ -353,19 +362,20 @@
|
| void HttpNetworkTransaction::BuildTunnelRequest() {
|
| // RFC 2616 Section 9 says the Host request-header field MUST accompany all
|
| // HTTP/1.1 requests.
|
| - request_headers_ = StringPrintf("CONNECT %s:%d HTTP/1.1\r\n",
|
| + request_headers_->headers_ = StringPrintf("CONNECT %s:%d HTTP/1.1\r\n",
|
| request_->url.host().c_str(), request_->url.EffectiveIntPort());
|
| - request_headers_ += "Host: " + request_->url.host();
|
| + request_headers_->headers_ += "Host: " + request_->url.host();
|
| if (request_->url.has_port())
|
| - request_headers_ += ":" + request_->url.port();
|
| - request_headers_ += "\r\n";
|
| + request_headers_->headers_ += ":" + request_->url.port();
|
| + request_headers_->headers_ += "\r\n";
|
|
|
| if (!request_->user_agent.empty())
|
| - request_headers_ += "User-Agent: " + request_->user_agent + "\r\n";
|
| + request_headers_->headers_ += "User-Agent: " + request_->user_agent +
|
| + "\r\n";
|
|
|
| ApplyAuth();
|
|
|
| - request_headers_ += "\r\n";
|
| + request_headers_->headers_ += "\r\n";
|
| }
|
|
|
| void HttpNetworkTransaction::DoCallback(int rv) {
|
| @@ -654,7 +664,7 @@
|
|
|
| // This is constructed lazily (instead of within our Start method), so that
|
| // we have proxy info available.
|
| - if (request_headers_.empty()) {
|
| + if (request_headers_->headers_.empty()) {
|
| if (establishing_tunnel_) {
|
| BuildTunnelRequest();
|
| } else {
|
| @@ -668,12 +678,12 @@
|
| response_.request_time = Time::Now();
|
| }
|
|
|
| - const char* buf = request_headers_.data() + request_headers_bytes_sent_;
|
| - int buf_len = static_cast<int>(request_headers_.size() -
|
| + request_headers_->SetDataOffset(request_headers_bytes_sent_);
|
| + int buf_len = static_cast<int>(request_headers_->headers_.size() -
|
| request_headers_bytes_sent_);
|
| DCHECK(buf_len > 0);
|
|
|
| - return connection_.socket()->Write(buf, buf_len, &io_callback_);
|
| + return connection_.socket()->Write(request_headers_, buf_len, &io_callback_);
|
| }
|
|
|
| int HttpNetworkTransaction::DoWriteHeadersComplete(int result) {
|
| @@ -681,7 +691,7 @@
|
| return HandleIOError(result);
|
|
|
| request_headers_bytes_sent_ += result;
|
| - if (request_headers_bytes_sent_ < request_headers_.size()) {
|
| + if (request_headers_bytes_sent_ < request_headers_->headers_.size()) {
|
| next_state_ = STATE_WRITE_HEADERS;
|
| } else if (!establishing_tunnel_ && request_body_stream_.get() &&
|
| request_body_stream_->size()) {
|
| @@ -700,11 +710,17 @@
|
|
|
| const char* buf = request_body_stream_->buf();
|
| int buf_len = static_cast<int>(request_body_stream_->buf_len());
|
| + DCHECK(!write_buffer_);
|
| + write_buffer_ = new IOBuffer(buf_len);
|
| + memcpy(write_buffer_->data(), buf, buf_len);
|
|
|
| - return connection_.socket()->Write(buf, buf_len, &io_callback_);
|
| + return connection_.socket()->Write(write_buffer_, buf_len, &io_callback_);
|
| }
|
|
|
| int HttpNetworkTransaction::DoWriteBodyComplete(int result) {
|
| + DCHECK(write_buffer_);
|
| + write_buffer_ = NULL;
|
| +
|
| if (result < 0)
|
| return HandleIOError(result);
|
|
|
| @@ -724,14 +740,13 @@
|
| // Grow the read buffer if necessary.
|
| if (header_buf_len_ == header_buf_capacity_) {
|
| header_buf_capacity_ += kHeaderBufInitialSize;
|
| - header_buf_.reset(static_cast<char*>(
|
| - realloc(header_buf_.release(), header_buf_capacity_)));
|
| + header_buf_->Realloc(header_buf_capacity_);
|
| }
|
|
|
| - char* buf = header_buf_.get() + header_buf_len_;
|
| int buf_len = header_buf_capacity_ - header_buf_len_;
|
| + header_buf_->set_data(header_buf_len_);
|
|
|
| - return connection_.socket()->Read(buf, buf_len, &io_callback_);
|
| + return connection_.socket()->Read(header_buf_, buf_len, &io_callback_);
|
| }
|
|
|
| int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() {
|
| @@ -792,12 +807,12 @@
|
| // Look for the start of the status line, if it hasn't been found yet.
|
| if (!has_found_status_line_start()) {
|
| header_buf_http_offset_ = HttpUtil::LocateStartOfStatusLine(
|
| - header_buf_.get(), header_buf_len_);
|
| + header_buf_->headers(), header_buf_len_);
|
| }
|
|
|
| if (has_found_status_line_start()) {
|
| int eoh = HttpUtil::LocateEndOfHeaders(
|
| - header_buf_.get(), header_buf_len_, header_buf_http_offset_);
|
| + header_buf_->headers(), header_buf_len_, header_buf_http_offset_);
|
| if (eoh == -1) {
|
| // Prevent growing the headers buffer indefinitely.
|
| if (header_buf_len_ >= kMaxHeaderBufSize)
|
| @@ -836,12 +851,13 @@
|
| return 0;
|
|
|
| // We may have some data remaining in the header buffer.
|
| - if (header_buf_.get() && header_buf_body_offset_ < header_buf_len_) {
|
| + if (header_buf_->headers() && header_buf_body_offset_ < header_buf_len_) {
|
| int n = std::min(read_buf_len_, header_buf_len_ - header_buf_body_offset_);
|
| - memcpy(read_buf_->data(), header_buf_.get() + header_buf_body_offset_, n);
|
| + memcpy(read_buf_->data(), header_buf_->headers() + header_buf_body_offset_,
|
| + n);
|
| header_buf_body_offset_ += n;
|
| if (header_buf_body_offset_ == header_buf_len_) {
|
| - header_buf_.reset();
|
| + header_buf_->Reset();
|
| header_buf_capacity_ = 0;
|
| header_buf_len_ = 0;
|
| header_buf_body_offset_ = -1;
|
| @@ -850,8 +866,7 @@
|
| }
|
|
|
| reading_body_from_socket_ = true;
|
| - return connection_.socket()->Read(read_buf_->data(), read_buf_len_,
|
| - &io_callback_);
|
| + return connection_.socket()->Read(read_buf_, read_buf_len_, &io_callback_);
|
| }
|
|
|
| int HttpNetworkTransaction::DoReadBodyComplete(int result) {
|
| @@ -1059,7 +1074,7 @@
|
| if (has_found_status_line_start()) {
|
| headers = new HttpResponseHeaders(
|
| HttpUtil::AssembleRawHeaders(
|
| - header_buf_.get(), header_buf_body_offset_));
|
| + header_buf_->headers(), header_buf_body_offset_));
|
| } else {
|
| // Fabricate a status line to to preserve the HTTP/0.9 version.
|
| // (otherwise HttpResponseHeaders will default it to HTTP/1.0).
|
| @@ -1087,7 +1102,7 @@
|
| }
|
| next_state_ = STATE_SSL_CONNECT;
|
| // Reset for the real request and response headers.
|
| - request_headers_.clear();
|
| + request_headers_->headers_.clear();
|
| request_headers_bytes_sent_ = 0;
|
| header_buf_len_ = 0;
|
| header_buf_body_offset_ = 0;
|
| @@ -1127,7 +1142,8 @@
|
| // If we've already received some bytes after the 1xx response,
|
| // move them to the beginning of header_buf_.
|
| if (header_buf_len_) {
|
| - memmove(header_buf_.get(), header_buf_.get() + header_buf_body_offset_,
|
| + memmove(header_buf_->headers(),
|
| + header_buf_->headers() + header_buf_body_offset_,
|
| header_buf_len_);
|
| }
|
| header_buf_body_offset_ = -1;
|
| @@ -1266,7 +1282,7 @@
|
|
|
| void HttpNetworkTransaction::ResetStateForRestart() {
|
| pending_auth_target_ = HttpAuth::AUTH_NONE;
|
| - header_buf_.reset();
|
| + header_buf_->Reset();
|
| header_buf_capacity_ = 0;
|
| header_buf_len_ = 0;
|
| header_buf_body_offset_ = -1;
|
| @@ -1275,7 +1291,7 @@
|
| response_body_read_ = 0;
|
| read_buf_ = NULL;
|
| read_buf_len_ = 0;
|
| - request_headers_.clear();
|
| + request_headers_->headers_.clear();
|
| request_headers_bytes_sent_ = 0;
|
| chunked_decoder_.reset();
|
| // Reset all the members of response_.
|
| @@ -1298,7 +1314,7 @@
|
| // first to recreate the SSL tunnel. 2) An empty request_headers_ causes
|
| // BuildRequestHeaders to be called, which rewinds request_body_stream_ to
|
| // the beginning of request_->upload_data.
|
| - request_headers_.clear();
|
| + request_headers_->headers_.clear();
|
| request_headers_bytes_sent_ = 0;
|
| next_state_ = STATE_INIT_CONNECTION; // Resend the request.
|
| return true;
|
| @@ -1362,7 +1378,7 @@
|
| auth_identity_[target].password,
|
| request_,
|
| &proxy_info_);
|
| - request_headers_ += HttpAuth::GetAuthorizationHeaderName(target) +
|
| + request_headers_->headers_ += HttpAuth::GetAuthorizationHeaderName(target) +
|
| ": " + credentials + "\r\n";
|
| }
|
|
|
|
|