| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/spdy/spdy_http_utils.h" | 5 #include "net/spdy/spdy_http_utils.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 namespace net { | 21 namespace net { |
| 22 | 22 |
| 23 namespace { | 23 namespace { |
| 24 | 24 |
| 25 void AddSpdyHeader(const std::string& name, | 25 void AddSpdyHeader(const std::string& name, |
| 26 const std::string& value, | 26 const std::string& value, |
| 27 SpdyHeaderBlock* headers) { | 27 SpdyHeaderBlock* headers) { |
| 28 if (headers->find(name) == headers->end()) { | 28 if (headers->find(name) == headers->end()) { |
| 29 (*headers)[name] = value; | 29 (*headers)[name] = value; |
| 30 } else { | 30 } else { |
| 31 (*headers)[name] += '\0' + value; | 31 std::string joint_value = (*headers)[name].as_string(); |
| 32 joint_value.append(1, '\0'); |
| 33 joint_value.append(value); |
| 34 (*headers)[name] = joint_value; |
| 32 } | 35 } |
| 33 } | 36 } |
| 34 | 37 |
| 35 } // namespace | 38 } // namespace |
| 36 | 39 |
| 37 bool SpdyHeadersToHttpResponse(const SpdyHeaderBlock& headers, | 40 bool SpdyHeadersToHttpResponse(const SpdyHeaderBlock& headers, |
| 38 SpdyMajorVersion protocol_version, | 41 SpdyMajorVersion protocol_version, |
| 39 HttpResponseInfo* response) { | 42 HttpResponseInfo* response) { |
| 40 std::string status_key = (protocol_version >= SPDY3) ? ":status" : "status"; | 43 std::string status_key = (protocol_version >= SPDY3) ? ":status" : "status"; |
| 41 std::string version_key = | 44 std::string version_key = |
| 42 (protocol_version >= SPDY3) ? ":version" : "version"; | 45 (protocol_version >= SPDY3) ? ":version" : "version"; |
| 43 std::string version; | 46 std::string version; |
| 44 std::string status; | 47 std::string status; |
| 45 | 48 |
| 46 // The "status" header is required. "version" is required below HTTP/2. | 49 // The "status" header is required. "version" is required below HTTP/2. |
| 47 SpdyHeaderBlock::const_iterator it; | 50 SpdyHeaderBlock::const_iterator it; |
| 48 it = headers.find(status_key); | 51 it = headers.find(status_key); |
| 49 if (it == headers.end()) | 52 if (it == headers.end()) |
| 50 return false; | 53 return false; |
| 51 status = it->second; | 54 status = it->second.as_string(); |
| 52 | 55 |
| 53 if (protocol_version >= HTTP2) { | 56 if (protocol_version >= HTTP2) { |
| 54 version = "HTTP/1.1"; | 57 version = "HTTP/1.1"; |
| 55 } else { | 58 } else { |
| 56 it = headers.find(version_key); | 59 it = headers.find(version_key); |
| 57 if (it == headers.end()) | 60 if (it == headers.end()) |
| 58 return false; | 61 return false; |
| 59 version = it->second; | 62 version = it->second.as_string(); |
| 60 } | 63 } |
| 61 std::string raw_headers(version); | 64 std::string raw_headers(version); |
| 62 raw_headers.push_back(' '); | 65 raw_headers.push_back(' '); |
| 63 raw_headers.append(status); | 66 raw_headers.append(status); |
| 64 raw_headers.push_back('\0'); | 67 raw_headers.push_back('\0'); |
| 65 for (it = headers.begin(); it != headers.end(); ++it) { | 68 for (it = headers.begin(); it != headers.end(); ++it) { |
| 66 // For each value, if the server sends a NUL-separated | 69 // For each value, if the server sends a NUL-separated |
| 67 // list of values, we separate that back out into | 70 // list of values, we separate that back out into |
| 68 // individual headers for each value in the list. | 71 // individual headers for each value in the list. |
| 69 // e.g. | 72 // e.g. |
| 70 // Set-Cookie "foo\0bar" | 73 // Set-Cookie "foo\0bar" |
| 71 // becomes | 74 // becomes |
| 72 // Set-Cookie: foo\0 | 75 // Set-Cookie: foo\0 |
| 73 // Set-Cookie: bar\0 | 76 // Set-Cookie: bar\0 |
| 74 std::string value = it->second; | 77 std::string value = it->second.as_string(); |
| 75 size_t start = 0; | 78 size_t start = 0; |
| 76 size_t end = 0; | 79 size_t end = 0; |
| 77 do { | 80 do { |
| 78 end = value.find('\0', start); | 81 end = value.find('\0', start); |
| 79 std::string tval; | 82 std::string tval; |
| 80 if (end != value.npos) | 83 if (end != value.npos) |
| 81 tval = value.substr(start, (end - start)); | 84 tval = value.substr(start, (end - start)); |
| 82 else | 85 else |
| 83 tval = value.substr(start); | 86 tval = value.substr(start); |
| 84 if (protocol_version >= 3 && it->first[0] == ':') | 87 if (protocol_version >= 3 && it->first[0] == ':') |
| 85 raw_headers.append(it->first.substr(1)); | 88 raw_headers.append(it->first.as_string().substr(1)); |
| 86 else | 89 else |
| 87 raw_headers.append(it->first); | 90 raw_headers.append(it->first.as_string()); |
| 88 raw_headers.push_back(':'); | 91 raw_headers.push_back(':'); |
| 89 raw_headers.append(tval); | 92 raw_headers.append(tval); |
| 90 raw_headers.push_back('\0'); | 93 raw_headers.push_back('\0'); |
| 91 start = end + 1; | 94 start = end + 1; |
| 92 } while (end != value.npos); | 95 } while (end != value.npos); |
| 93 } | 96 } |
| 94 | 97 |
| 95 response->headers = new HttpResponseHeaders(raw_headers); | 98 response->headers = new HttpResponseHeaders(raw_headers); |
| 96 response->was_fetched_via_spdy = true; | 99 response->was_fetched_via_spdy = true; |
| 97 return true; | 100 return true; |
| 98 } | 101 } |
| 99 | 102 |
| 100 void CreateSpdyHeadersFromHttpRequest(const HttpRequestInfo& info, | 103 void CreateSpdyHeadersFromHttpRequest(const HttpRequestInfo& info, |
| 101 const HttpRequestHeaders& request_headers, | 104 const HttpRequestHeaders& request_headers, |
| 102 SpdyMajorVersion protocol_version, | 105 SpdyMajorVersion protocol_version, |
| 103 bool direct, | 106 bool direct, |
| 104 SpdyHeaderBlock* headers) { | 107 SpdyHeaderBlock* headers) { |
| 105 | |
| 106 HttpRequestHeaders::Iterator it(request_headers); | |
| 107 while (it.GetNext()) { | |
| 108 std::string name = base::ToLowerASCII(it.name()); | |
| 109 if (name == "connection" || name == "proxy-connection" || | |
| 110 name == "transfer-encoding" || name == "host") { | |
| 111 continue; | |
| 112 } | |
| 113 AddSpdyHeader(name, it.value(), headers); | |
| 114 } | |
| 115 static const char kHttpProtocolVersion[] = "HTTP/1.1"; | 108 static const char kHttpProtocolVersion[] = "HTTP/1.1"; |
| 116 | |
| 117 switch (protocol_version) { | 109 switch (protocol_version) { |
| 118 case SPDY2: | 110 case SPDY2: |
| 119 // TODO(bnc): Remove this code now that SPDY/2 is deprecated. | 111 // TODO(bnc): Remove this code now that SPDY/2 is deprecated. |
| 120 (*headers)["version"] = kHttpProtocolVersion; | 112 (*headers)["version"] = kHttpProtocolVersion; |
| 121 (*headers)["method"] = info.method; | 113 (*headers)["method"] = info.method; |
| 122 (*headers)["host"] = GetHostAndOptionalPort(info.url); | 114 (*headers)["host"] = GetHostAndOptionalPort(info.url); |
| 123 if (info.method == "CONNECT") { | 115 if (info.method == "CONNECT") { |
| 124 (*headers)["url"] = GetHostAndPort(info.url); | 116 (*headers)["url"] = GetHostAndPort(info.url); |
| 125 } else { | 117 } else { |
| 126 (*headers)["scheme"] = info.url.scheme(); | 118 (*headers)["scheme"] = info.url.scheme(); |
| 127 (*headers)["url"] = direct ? info.url.PathForRequest() | 119 (*headers)["url"] = direct ? info.url.PathForRequest() |
| 128 : HttpUtil::SpecForRequest(info.url); | 120 : HttpUtil::SpecForRequest(info.url); |
| 129 } | 121 } |
| 130 break; | 122 break; |
| 131 case SPDY3: | 123 case SPDY3: |
| 132 (*headers)[":version"] = kHttpProtocolVersion; | 124 (*headers)[":version"] = kHttpProtocolVersion; |
| 125 (*headers)[":method"] = info.method; |
| 133 (*headers)[":host"] = GetHostAndOptionalPort(info.url); | 126 (*headers)[":host"] = GetHostAndOptionalPort(info.url); |
| 134 (*headers)[":method"] = info.method; | |
| 135 if (info.method == "CONNECT") { | 127 if (info.method == "CONNECT") { |
| 136 (*headers)[":path"] = GetHostAndPort(info.url); | 128 (*headers)[":path"] = GetHostAndPort(info.url); |
| 137 } else { | 129 } else { |
| 138 (*headers)[":scheme"] = info.url.scheme(); | 130 (*headers)[":scheme"] = info.url.scheme(); |
| 139 (*headers)[":path"] = info.url.PathForRequest(); | 131 (*headers)[":path"] = info.url.PathForRequest(); |
| 140 } | 132 } |
| 141 break; | 133 break; |
| 142 case HTTP2: | 134 case HTTP2: |
| 143 (*headers)[":method"] = info.method; | 135 (*headers)[":method"] = info.method; |
| 144 if (info.method == "CONNECT") { | 136 if (info.method == "CONNECT") { |
| 145 (*headers)[":authority"] = GetHostAndPort(info.url); | 137 (*headers)[":authority"] = GetHostAndPort(info.url); |
| 146 } else { | 138 } else { |
| 147 (*headers)[":authority"] = GetHostAndOptionalPort(info.url); | 139 (*headers)[":authority"] = GetHostAndOptionalPort(info.url); |
| 148 (*headers)[":scheme"] = info.url.scheme(); | 140 (*headers)[":scheme"] = info.url.scheme(); |
| 149 (*headers)[":path"] = info.url.PathForRequest(); | 141 (*headers)[":path"] = info.url.PathForRequest(); |
| 150 } | 142 } |
| 151 break; | 143 break; |
| 152 default: | 144 default: |
| 153 NOTREACHED(); | 145 NOTREACHED(); |
| 154 } | 146 } |
| 147 |
| 148 HttpRequestHeaders::Iterator it(request_headers); |
| 149 while (it.GetNext()) { |
| 150 std::string name = base::ToLowerASCII(it.name()); |
| 151 if (name.empty() || name[0] == ':' || name == "connection" || |
| 152 name == "proxy-connection" || name == "transfer-encoding" || |
| 153 name == "host") { |
| 154 continue; |
| 155 } |
| 156 AddSpdyHeader(name, it.value(), headers); |
| 157 } |
| 155 } | 158 } |
| 156 | 159 |
| 157 void CreateSpdyHeadersFromHttpResponse( | 160 void CreateSpdyHeadersFromHttpResponse( |
| 158 const HttpResponseHeaders& response_headers, | 161 const HttpResponseHeaders& response_headers, |
| 159 SpdyMajorVersion protocol_version, | 162 SpdyMajorVersion protocol_version, |
| 160 SpdyHeaderBlock* headers) { | 163 SpdyHeaderBlock* headers) { |
| 161 std::string status_key = (protocol_version >= SPDY3) ? ":status" : "status"; | 164 std::string status_key = (protocol_version >= SPDY3) ? ":status" : "status"; |
| 162 std::string version_key = | 165 std::string version_key = |
| 163 (protocol_version >= SPDY3) ? ":version" : "version"; | 166 (protocol_version >= SPDY3) ? ":version" : "version"; |
| 164 | 167 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 IDLE : static_cast<RequestPriority>(4 - priority); | 201 IDLE : static_cast<RequestPriority>(4 - priority); |
| 199 } | 202 } |
| 200 | 203 |
| 201 GURL GetUrlFromHeaderBlock(const SpdyHeaderBlock& headers, | 204 GURL GetUrlFromHeaderBlock(const SpdyHeaderBlock& headers, |
| 202 SpdyMajorVersion protocol_version, | 205 SpdyMajorVersion protocol_version, |
| 203 bool pushed) { | 206 bool pushed) { |
| 204 DCHECK_LE(SPDY3, protocol_version); | 207 DCHECK_LE(SPDY3, protocol_version); |
| 205 SpdyHeaderBlock::const_iterator it = headers.find(":scheme"); | 208 SpdyHeaderBlock::const_iterator it = headers.find(":scheme"); |
| 206 if (it == headers.end()) | 209 if (it == headers.end()) |
| 207 return GURL(); | 210 return GURL(); |
| 208 std::string url = it->second; | 211 std::string url = it->second.as_string(); |
| 209 url.append("://"); | 212 url.append("://"); |
| 210 | 213 |
| 211 it = headers.find(protocol_version >= HTTP2 ? ":authority" : ":host"); | 214 it = headers.find(protocol_version >= HTTP2 ? ":authority" : ":host"); |
| 212 if (it == headers.end()) | 215 if (it == headers.end()) |
| 213 return GURL(); | 216 return GURL(); |
| 214 url.append(it->second); | 217 url.append(it->second.as_string()); |
| 215 | 218 |
| 216 it = headers.find(":path"); | 219 it = headers.find(":path"); |
| 217 if (it == headers.end()) | 220 if (it == headers.end()) |
| 218 return GURL(); | 221 return GURL(); |
| 219 url.append(it->second); | 222 url.append(it->second.as_string()); |
| 220 return GURL(url); | 223 return GURL(url); |
| 221 } | 224 } |
| 222 | 225 |
| 223 } // namespace net | 226 } // namespace net |
| OLD | NEW |