summaryrefslogtreecommitdiff
path: root/chromium/net/spdy/spdy_http_utils.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/net/spdy/spdy_http_utils.cc')
-rw-r--r--chromium/net/spdy/spdy_http_utils.cc203
1 files changed, 203 insertions, 0 deletions
diff --git a/chromium/net/spdy/spdy_http_utils.cc b/chromium/net/spdy/spdy_http_utils.cc
new file mode 100644
index 00000000000..21012f23fc1
--- /dev/null
+++ b/chromium/net/spdy/spdy_http_utils.cc
@@ -0,0 +1,203 @@
+// Copyright (c) 2012 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 <string>
+
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/time/time.h"
+#include "net/base/escape.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 SpdyHeaderBlock& headers,
+ int protocol_version,
+ HttpResponseInfo* response) {
+ std::string status_key = (protocol_version >= 3) ? ":status" : "status";
+ std::string version_key = (protocol_version >= 3) ? ":version" : "version";
+ std::string version;
+ std::string status;
+
+ // The "status" and "version" headers are required.
+ SpdyHeaderBlock::const_iterator it;
+ it = headers.find(status_key);
+ if (it == headers.end())
+ return false;
+ status = it->second;
+
+ it = headers.find(version_key);
+ if (it == headers.end())
+ return false;
+ version = it->second;
+
+ 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);
+ if (protocol_version >= 3 && it->first[0] == ':')
+ raw_headers.append(it->first.substr(1));
+ else
+ 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,
+ const HttpRequestHeaders& request_headers,
+ SpdyHeaderBlock* headers,
+ int protocol_version,
+ bool direct) {
+
+ HttpRequestHeaders::Iterator it(request_headers);
+ while (it.GetNext()) {
+ std::string name = StringToLowerASCII(it.name());
+ if (name == "connection" || name == "proxy-connection" ||
+ name == "transfer-encoding") {
+ continue;
+ }
+ 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;
+ }
+ }
+ static const char kHttpProtocolVersion[] = "HTTP/1.1";
+
+ if (protocol_version < 3) {
+ (*headers)["version"] = kHttpProtocolVersion;
+ (*headers)["method"] = info.method;
+ (*headers)["host"] = GetHostAndOptionalPort(info.url);
+ (*headers)["scheme"] = info.url.scheme();
+ if (direct)
+ (*headers)["url"] = HttpUtil::PathForRequest(info.url);
+ else
+ (*headers)["url"] = HttpUtil::SpecForRequest(info.url);
+ } else {
+ (*headers)[":version"] = kHttpProtocolVersion;
+ (*headers)[":method"] = info.method;
+ (*headers)[":host"] = GetHostAndOptionalPort(info.url);
+ (*headers)[":scheme"] = info.url.scheme();
+ (*headers)[":path"] = HttpUtil::PathForRequest(info.url);
+ headers->erase("host"); // this is kinda insane, spdy 3 spec.
+ }
+
+}
+
+COMPILE_ASSERT(HIGHEST - LOWEST < 4 &&
+ HIGHEST - MINIMUM_PRIORITY < 5,
+ request_priority_incompatible_with_spdy);
+
+SpdyPriority ConvertRequestPriorityToSpdyPriority(
+ const RequestPriority priority,
+ int protocol_version) {
+ DCHECK_GE(priority, MINIMUM_PRIORITY);
+ DCHECK_LT(priority, NUM_PRIORITIES);
+ if (protocol_version == 2) {
+ // SPDY 2 only has 2 bits of priority, but we have 5 RequestPriorities.
+ // Map IDLE => 3, LOWEST => 2, LOW => 2, MEDIUM => 1, HIGHEST => 0.
+ if (priority > LOWEST) {
+ return static_cast<SpdyPriority>(HIGHEST - priority);
+ } else {
+ return static_cast<SpdyPriority>(HIGHEST - priority - 1);
+ }
+ } else {
+ return static_cast<SpdyPriority>(HIGHEST - priority);
+ }
+}
+
+NET_EXPORT_PRIVATE RequestPriority ConvertSpdyPriorityToRequestPriority(
+ SpdyPriority priority,
+ int protocol_version) {
+ // Handle invalid values gracefully, and pick LOW to map 2 back
+ // to for SPDY/2.
+ SpdyPriority idle_cutoff = (protocol_version == 2) ? 3 : 5;
+ return (priority >= idle_cutoff) ?
+ IDLE : static_cast<RequestPriority>(HIGHEST - priority);
+}
+
+GURL GetUrlFromHeaderBlock(const SpdyHeaderBlock& headers,
+ int protocol_version,
+ bool pushed) {
+ // SPDY 2 server push urls are specified in a single "url" header.
+ if (pushed && protocol_version == 2) {
+ std::string url;
+ SpdyHeaderBlock::const_iterator it;
+ it = headers.find("url");
+ if (it != headers.end())
+ url = it->second;
+ return GURL(url);
+ }
+
+ const char* scheme_header = protocol_version >= 3 ? ":scheme" : "scheme";
+ const char* host_header = protocol_version >= 3 ? ":host" : "host";
+ const char* path_header = protocol_version >= 3 ? ":path" : "url";
+
+ std::string scheme;
+ std::string host_port;
+ std::string path;
+ SpdyHeaderBlock::const_iterator it;
+ it = headers.find(scheme_header);
+ if (it != headers.end())
+ scheme = it->second;
+ it = headers.find(host_header);
+ if (it != headers.end())
+ host_port = it->second;
+ it = headers.find(path_header);
+ if (it != headers.end())
+ path = it->second;
+
+ std::string url = (scheme.empty() || host_port.empty() || path.empty())
+ ? std::string()
+ : scheme + "://" + host_port + path;
+ return GURL(url);
+}
+
+bool ShouldShowHttpHeaderValue(const std::string& header_name) {
+#if defined(SPDY_PROXY_AUTH_ORIGIN)
+ if (header_name == "proxy-authorization")
+ return false;
+#endif
+ return true;
+}
+
+} // namespace net