diff options
-rw-r--r-- | net/net.gyp | 2 | ||||
-rw-r--r-- | net/spdy/spdy_http_stream.cc | 137 | ||||
-rw-r--r-- | net/spdy/spdy_http_utils.cc | 141 | ||||
-rw-r--r-- | net/spdy/spdy_http_utils.h | 32 |
4 files changed, 176 insertions, 136 deletions
diff --git a/net/net.gyp b/net/net.gyp index 2b43f9f..b9e16cc 100644 --- a/net/net.gyp +++ b/net/net.gyp @@ -565,6 +565,8 @@ 'spdy/spdy_framer.h', 'spdy/spdy_http_stream.cc', 'spdy/spdy_http_stream.h', + 'spdy/spdy_http_utils.cc', + 'spdy/spdy_http_utils.h', 'spdy/spdy_io_buffer.cc', 'spdy/spdy_io_buffer.h', 'spdy/spdy_protocol.h', diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc index 2880b07..0e3962e 100644 --- a/net/spdy/spdy_http_stream.cc +++ b/net/spdy/spdy_http_stream.cc @@ -10,149 +10,14 @@ #include "base/logging.h" #include "base/message_loop.h" -#include "base/string_number_conversions.h" -#include "base/string_util.h" #include "net/base/load_flags.h" #include "net/base/net_util.h" -#include "net/base/ssl_cert_request_info.h" #include "net/http/http_request_info.h" -#include "net/http/http_response_headers.h" #include "net/http/http_response_info.h" #include "net/http/http_util.h" +#include "net/spdy/spdy_http_utils.h" #include "net/spdy/spdy_session.h" -namespace { - -// Convert a SpdyHeaderBlock into an HttpResponseInfo. -// |headers| input parameter with the SpdyHeaderBlock. -// |info| output parameter for the HttpResponseInfo. -// Returns true if successfully converted. False if there was a failure -// or if the SpdyHeaderBlock was invalid. -bool SpdyHeadersToHttpResponse(const spdy::SpdyHeaderBlock& headers, - net::HttpResponseInfo* response) { - std::string version; - std::string status; - - // The "status" and "version" headers are required. - spdy::SpdyHeaderBlock::const_iterator it; - it = headers.find("status"); - if (it == headers.end()) { - LOG(ERROR) << "SpdyHeaderBlock without status header."; - return false; - } - status = it->second; - - // Grab the version. If not provided by the server, - it = headers.find("version"); - if (it == headers.end()) { - LOG(ERROR) << "SpdyHeaderBlock without version header."; - return false; - } - version = it->second; - - response->response_time = base::Time::Now(); - - std::string raw_headers(version); - raw_headers.push_back(' '); - raw_headers.append(status); - raw_headers.push_back('\0'); - for (it = headers.begin(); it != headers.end(); ++it) { - // For each value, if the server sends a NUL-separated - // list of values, we separate that back out into - // individual headers for each value in the list. - // e.g. - // Set-Cookie "foo\0bar" - // becomes - // Set-Cookie: foo\0 - // Set-Cookie: bar\0 - std::string value = it->second; - size_t start = 0; - size_t end = 0; - do { - end = value.find('\0', start); - std::string tval; - if (end != value.npos) - tval = value.substr(start, (end - start)); - else - tval = value.substr(start); - raw_headers.append(it->first); - raw_headers.push_back(':'); - raw_headers.append(tval); - raw_headers.push_back('\0'); - start = end + 1; - } while (end != value.npos); - } - - response->headers = new net::HttpResponseHeaders(raw_headers); - response->was_fetched_via_spdy = true; - return true; -} - -// Create a SpdyHeaderBlock for a Spdy SYN_STREAM Frame from -// a HttpRequestInfo block. -void CreateSpdyHeadersFromHttpRequest( - const net::HttpRequestInfo& info, spdy::SpdyHeaderBlock* headers, - bool direct) { - // TODO(willchan): It's not really necessary to convert from - // HttpRequestHeaders to spdy::SpdyHeaderBlock. - - static const char kHttpProtocolVersion[] = "HTTP/1.1"; - - net::HttpRequestHeaders::Iterator it(info.extra_headers); - - while (it.GetNext()) { - std::string name = StringToLowerASCII(it.name()); - if (headers->find(name) == headers->end()) { - (*headers)[name] = it.value(); - } else { - std::string new_value = (*headers)[name]; - new_value.append(1, '\0'); // +=() doesn't append 0's - new_value += it.value(); - (*headers)[name] = new_value; - } - } - - // TODO(mbelshe): Add Proxy headers here. (See http_network_transaction.cc) - // TODO(mbelshe): Add authentication headers here. - - (*headers)["method"] = info.method; - - // Handle content-length. This is the same as BuildRequestHeader in - // http_network_transaction.cc. - // TODO(lzheng): reduce the code duplication between spdy and http here. - if (info.upload_data) { - (*headers)["content-length"] = - base::Int64ToString(info.upload_data->GetContentLength()); - } else if (info.method == "POST" || info.method == "PUT" || - info.method == "HEAD") { - // An empty POST/PUT request still needs a content length. As for HEAD, - // 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. - (*headers)["content-length"] = "0"; - } - - if (direct) - (*headers)["url"] = net::HttpUtil::PathForRequest(info.url); - else - (*headers)["url"] = net::HttpUtil::SpecForRequest(info.url); - (*headers)["host"] = net::GetHostAndOptionalPort(info.url); - (*headers)["scheme"] = info.url.scheme(); - (*headers)["version"] = kHttpProtocolVersion; - if (!info.referrer.is_empty()) - (*headers)["referer"] = info.referrer.spec(); - - // Honor load flags that impact proxy caches. - if (info.load_flags & net::LOAD_BYPASS_CACHE) { - (*headers)["pragma"] = "no-cache"; - (*headers)["cache-control"] = "no-cache"; - } else if (info.load_flags & net::LOAD_VALIDATE_CACHE) { - (*headers)["cache-control"] = "max-age=0"; - } -} - -} // anonymous namespace - namespace net { SpdyHttpStream::SpdyHttpStream(SpdySession* spdy_session, bool direct) diff --git a/net/spdy/spdy_http_utils.cc b/net/spdy/spdy_http_utils.cc new file mode 100644 index 0000000..d2fdd8fa --- /dev/null +++ b/net/spdy/spdy_http_utils.cc @@ -0,0 +1,141 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/spdy/spdy_http_utils.h" + +#include "base/string_number_conversions.h" +#include "base/string_util.h" +#include "base/time.h" +#include "net/base/load_flags.h" +#include "net/base/net_util.h" +#include "net/http/http_request_headers.h" +#include "net/http/http_request_info.h" +#include "net/http/http_response_headers.h" +#include "net/http/http_response_info.h" +#include "net/http/http_util.h" + +namespace net { + +bool SpdyHeadersToHttpResponse(const spdy::SpdyHeaderBlock& headers, + HttpResponseInfo* response) { + std::string version; + std::string status; + + // The "status" and "version" headers are required. + spdy::SpdyHeaderBlock::const_iterator it; + it = headers.find("status"); + if (it == headers.end()) { + LOG(ERROR) << "SpdyHeaderBlock without status header."; + return false; + } + status = it->second; + + // Grab the version. If not provided by the server, + it = headers.find("version"); + if (it == headers.end()) { + LOG(ERROR) << "SpdyHeaderBlock without version header."; + return false; + } + version = it->second; + + response->response_time = base::Time::Now(); + + std::string raw_headers(version); + raw_headers.push_back(' '); + raw_headers.append(status); + raw_headers.push_back('\0'); + for (it = headers.begin(); it != headers.end(); ++it) { + // For each value, if the server sends a NUL-separated + // list of values, we separate that back out into + // individual headers for each value in the list. + // e.g. + // Set-Cookie "foo\0bar" + // becomes + // Set-Cookie: foo\0 + // Set-Cookie: bar\0 + std::string value = it->second; + size_t start = 0; + size_t end = 0; + do { + end = value.find('\0', start); + std::string tval; + if (end != value.npos) + tval = value.substr(start, (end - start)); + else + tval = value.substr(start); + raw_headers.append(it->first); + raw_headers.push_back(':'); + raw_headers.append(tval); + raw_headers.push_back('\0'); + start = end + 1; + } while (end != value.npos); + } + + response->headers = new HttpResponseHeaders(raw_headers); + response->was_fetched_via_spdy = true; + return true; +} + +void CreateSpdyHeadersFromHttpRequest( + const HttpRequestInfo& info, spdy::SpdyHeaderBlock* headers, + bool direct) { + // TODO(willchan): It's not really necessary to convert from + // HttpRequestHeaders to spdy::SpdyHeaderBlock. + + static const char kHttpProtocolVersion[] = "HTTP/1.1"; + + HttpRequestHeaders::Iterator it(info.extra_headers); + + while (it.GetNext()) { + std::string name = StringToLowerASCII(it.name()); + if (headers->find(name) == headers->end()) { + (*headers)[name] = it.value(); + } else { + std::string new_value = (*headers)[name]; + new_value.append(1, '\0'); // +=() doesn't append 0's + new_value += it.value(); + (*headers)[name] = new_value; + } + } + + // TODO(rch): Add Proxy headers here. (See http_network_transaction.cc) + // TODO(rch): Add authentication headers here. + + (*headers)["method"] = info.method; + + // Handle content-length. This is the same as BuildRequestHeader in + // http_network_transaction.cc. + // TODO(lzheng): reduce the code duplication between spdy and http here. + if (info.upload_data) { + (*headers)["content-length"] = + base::Int64ToString(info.upload_data->GetContentLength()); + } else if (info.method == "POST" || info.method == "PUT" || + info.method == "HEAD") { + // An empty POST/PUT request still needs a content length. As for HEAD, + // 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. + (*headers)["content-length"] = "0"; + } + + if (direct) + (*headers)["url"] = HttpUtil::PathForRequest(info.url); + else + (*headers)["url"] = HttpUtil::SpecForRequest(info.url); + (*headers)["host"] = GetHostAndOptionalPort(info.url); + (*headers)["scheme"] = info.url.scheme(); + (*headers)["version"] = kHttpProtocolVersion; + if (!info.referrer.is_empty()) + (*headers)["referer"] = info.referrer.spec(); + + // Honor load flags that impact proxy caches. + if (info.load_flags & LOAD_BYPASS_CACHE) { + (*headers)["pragma"] = "no-cache"; + (*headers)["cache-control"] = "no-cache"; + } else if (info.load_flags & LOAD_VALIDATE_CACHE) { + (*headers)["cache-control"] = "max-age=0"; + } +} + +} // namespace net diff --git a/net/spdy/spdy_http_utils.h b/net/spdy/spdy_http_utils.h new file mode 100644 index 0000000..0889921 --- /dev/null +++ b/net/spdy/spdy_http_utils.h @@ -0,0 +1,32 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_SPDY_SPDY_HTTP_UTILS_H_ +#define NET_SPDY_SPDY_HTTP_UTILS_H_ +#pragma once + +#include "net/spdy/spdy_framer.h" + +namespace net { + +class HttpResponseInfo; +class HttpRequestInfo; + +// Convert a SpdyHeaderBlock into an HttpResponseInfo. +// |headers| input parameter with the SpdyHeaderBlock. +// |info| output parameter for the HttpResponseInfo. +// Returns true if successfully converted. False if there was a failure +// or if the SpdyHeaderBlock was invalid. +bool SpdyHeadersToHttpResponse(const spdy::SpdyHeaderBlock& headers, + HttpResponseInfo* response); + +// Create a SpdyHeaderBlock for a Spdy SYN_STREAM Frame from +// a HttpRequestInfo block. +void CreateSpdyHeadersFromHttpRequest(const HttpRequestInfo& info, + spdy::SpdyHeaderBlock* headers, + bool direct); + +} // namespace net + +#endif // NET_SPDY_SPDY_HTTP_UTILS_H_ |