1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/spdy/spdy_http_utils.h" 6 7 #include <string> 8 9 #include "base/string_number_conversions.h" 10 #include "base/string_util.h" 11 #include "base/time.h" 12 #include "net/base/load_flags.h" 13 #include "net/base/net_util.h" 14 #include "net/http/http_request_headers.h" 15 #include "net/http/http_request_info.h" 16 #include "net/http/http_response_headers.h" 17 #include "net/http/http_response_info.h" 18 #include "net/http/http_util.h" 19 20 namespace net { 21 22 bool SpdyHeadersToHttpResponse(const spdy::SpdyHeaderBlock& headers, 23 HttpResponseInfo* response) { 24 std::string version; 25 std::string status; 26 27 // The "status" and "version" headers are required. 28 spdy::SpdyHeaderBlock::const_iterator it; 29 it = headers.find("status"); 30 if (it == headers.end()) 31 return false; 32 status = it->second; 33 34 // Grab the version. If not provided by the server, 35 it = headers.find("version"); 36 if (it == headers.end()) 37 return false; 38 version = it->second; 39 40 response->response_time = base::Time::Now(); 41 42 std::string raw_headers(version); 43 raw_headers.push_back(' '); 44 raw_headers.append(status); 45 raw_headers.push_back('\0'); 46 for (it = headers.begin(); it != headers.end(); ++it) { 47 // For each value, if the server sends a NUL-separated 48 // list of values, we separate that back out into 49 // individual headers for each value in the list. 50 // e.g. 51 // Set-Cookie "foo\0bar" 52 // becomes 53 // Set-Cookie: foo\0 54 // Set-Cookie: bar\0 55 std::string value = it->second; 56 size_t start = 0; 57 size_t end = 0; 58 do { 59 end = value.find('\0', start); 60 std::string tval; 61 if (end != value.npos) 62 tval = value.substr(start, (end - start)); 63 else 64 tval = value.substr(start); 65 raw_headers.append(it->first); 66 raw_headers.push_back(':'); 67 raw_headers.append(tval); 68 raw_headers.push_back('\0'); 69 start = end + 1; 70 } while (end != value.npos); 71 } 72 73 response->headers = new HttpResponseHeaders(raw_headers); 74 response->was_fetched_via_spdy = true; 75 return true; 76 } 77 78 void CreateSpdyHeadersFromHttpRequest(const HttpRequestInfo& info, 79 const HttpRequestHeaders& request_headers, 80 spdy::SpdyHeaderBlock* headers, 81 bool direct) { 82 83 HttpRequestHeaders::Iterator it(request_headers); 84 while (it.GetNext()) { 85 std::string name = StringToLowerASCII(it.name()); 86 if (name == "connection" || name == "proxy-connection" || 87 name == "transfer-encoding") { 88 continue; 89 } 90 if (headers->find(name) == headers->end()) { 91 (*headers)[name] = it.value(); 92 } else { 93 std::string new_value = (*headers)[name]; 94 new_value.append(1, '\0'); // +=() doesn't append 0's 95 new_value += it.value(); 96 (*headers)[name] = new_value; 97 } 98 } 99 static const char kHttpProtocolVersion[] = "HTTP/1.1"; 100 101 (*headers)["version"] = kHttpProtocolVersion; 102 (*headers)["method"] = info.method; 103 (*headers)["host"] = GetHostAndOptionalPort(info.url); 104 (*headers)["scheme"] = info.url.scheme(); 105 if (direct) 106 (*headers)["url"] = HttpUtil::PathForRequest(info.url); 107 else 108 (*headers)["url"] = HttpUtil::SpecForRequest(info.url); 109 110 } 111 112 // TODO(gavinp): re-adjust this once SPDY v3 has three priority bits, 113 // eliminating the need for this folding. 114 int ConvertRequestPriorityToSpdyPriority(const RequestPriority priority) { 115 DCHECK(HIGHEST <= priority && priority < NUM_PRIORITIES); 116 switch (priority) { 117 case LOWEST: 118 return SPDY_PRIORITY_LOWEST - 1; 119 case IDLE: 120 return SPDY_PRIORITY_LOWEST; 121 default: 122 return priority; 123 } 124 } 125 126 } // namespace net 127