1 // Copyright 2014 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 "components/data_reduction_proxy/common/data_reduction_proxy_headers.h" 6 7 #include "net/http/http_response_headers.h" 8 #include "net/proxy/proxy_service.h" 9 #include "testing/gtest/include/gtest/gtest.h" 10 11 namespace { 12 13 // Transform "normal"-looking headers (\n-separated) to the appropriate 14 // input format for ParseRawHeaders (\0-separated). 15 void HeadersToRaw(std::string* headers) { 16 std::replace(headers->begin(), headers->end(), '\n', '\0'); 17 if (!headers->empty()) 18 *headers += '\0'; 19 } 20 21 } // namespace 22 23 namespace data_reduction_proxy { 24 25 class DataReductionProxyHeadersTest : public testing::Test {}; 26 27 TEST_F(DataReductionProxyHeadersTest, GetProxyBypassInfo) { 28 const struct { 29 const char* headers; 30 bool expected_result; 31 int64 expected_retry_delay; 32 bool expected_bypass_all; 33 } tests[] = { 34 { "HTTP/1.1 200 OK\n" 35 "Content-Length: 999\n", 36 false, 37 0, 38 false, 39 }, 40 { "HTTP/1.1 200 OK\n" 41 "connection: keep-alive\n" 42 "Content-Length: 999\n", 43 false, 44 0, 45 false, 46 }, 47 { "HTTP/1.1 200 OK\n" 48 "connection: keep-alive\n" 49 "Chrome-Proxy: bypass=86400\n" 50 "Content-Length: 999\n", 51 true, 52 86400, 53 false, 54 }, 55 { "HTTP/1.1 200 OK\n" 56 "connection: keep-alive\n" 57 "Chrome-Proxy: bypass=0\n" 58 "Content-Length: 999\n", 59 true, 60 0, 61 false, 62 }, 63 { "HTTP/1.1 200 OK\n" 64 "connection: keep-alive\n" 65 "Chrome-Proxy: bypass=-1\n" 66 "Content-Length: 999\n", 67 false, 68 0, 69 false, 70 }, 71 { "HTTP/1.1 200 OK\n" 72 "connection: keep-alive\n" 73 "Chrome-Proxy: bypass=xyz\n" 74 "Content-Length: 999\n", 75 false, 76 0, 77 false, 78 }, 79 { "HTTP/1.1 200 OK\n" 80 "connection: keep-alive\n" 81 "Chrome-Proxy: bypass\n" 82 "Content-Length: 999\n", 83 false, 84 0, 85 false, 86 }, 87 { "HTTP/1.1 200 OK\n" 88 "connection: keep-alive\n" 89 "Chrome-Proxy: foo=abc, bypass=86400\n" 90 "Content-Length: 999\n", 91 true, 92 86400, 93 false, 94 }, 95 { "HTTP/1.1 200 OK\n" 96 "connection: keep-alive\n" 97 "Chrome-Proxy: bypass=86400, bar=abc\n" 98 "Content-Length: 999\n", 99 true, 100 86400, 101 false, 102 }, 103 { "HTTP/1.1 200 OK\n" 104 "connection: keep-alive\n" 105 "Chrome-Proxy: bypass=3600\n" 106 "Chrome-Proxy: bypass=86400\n" 107 "Content-Length: 999\n", 108 true, 109 3600, 110 false, 111 }, 112 { "HTTP/1.1 200 OK\n" 113 "connection: keep-alive\n" 114 "Chrome-Proxy: bypass=3600, bypass=86400\n" 115 "Content-Length: 999\n", 116 true, 117 3600, 118 false, 119 }, 120 { "HTTP/1.1 200 OK\n" 121 "connection: keep-alive\n" 122 "Chrome-Proxy: bypass=, bypass=86400\n" 123 "Content-Length: 999\n", 124 true, 125 86400, 126 false, 127 }, 128 { "HTTP/1.1 200 OK\n" 129 "connection: keep-alive\n" 130 "Chrome-Proxy: bypass\n" 131 "Chrome-Proxy: bypass=86400\n" 132 "Content-Length: 999\n", 133 true, 134 86400, 135 false, 136 }, 137 { "HTTP/1.1 200 OK\n" 138 "connection: keep-alive\n" 139 "Chrome-Proxy: block=, block=3600\n" 140 "Content-Length: 999\n", 141 true, 142 3600, 143 true, 144 }, 145 { "HTTP/1.1 200 OK\n" 146 "connection: keep-alive\n" 147 "Chrome-Proxy: bypass=86400, block=3600\n" 148 "Content-Length: 999\n", 149 true, 150 3600, 151 true, 152 }, 153 { "HTTP/1.1 200 OK\n" 154 "connection: proxy-bypass\n" 155 "Chrome-Proxy: block=, bypass=86400\n" 156 "Content-Length: 999\n", 157 true, 158 86400, 159 false, 160 }, 161 { "HTTP/1.1 200 OK\n" 162 "connection: proxy-bypass\n" 163 "Chrome-Proxy: block=-1\n" 164 "Content-Length: 999\n", 165 false, 166 0, 167 false, 168 }, 169 { "HTTP/1.1 200 OK\n" 170 "connection: proxy-bypass\n" 171 "Chrome-Proxy: block=99999999999999999999\n" 172 "Content-Length: 999\n", 173 false, 174 0, 175 false, 176 }, 177 }; 178 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 179 std::string headers(tests[i].headers); 180 HeadersToRaw(&headers); 181 scoped_refptr<net::HttpResponseHeaders> parsed( 182 new net::HttpResponseHeaders(headers)); 183 184 DataReductionProxyInfo data_reduction_proxy_info; 185 EXPECT_EQ(tests[i].expected_result, 186 GetDataReductionProxyInfo(parsed, &data_reduction_proxy_info)); 187 EXPECT_EQ(tests[i].expected_retry_delay, 188 data_reduction_proxy_info.bypass_duration.InSeconds()); 189 EXPECT_EQ(tests[i].expected_bypass_all, 190 data_reduction_proxy_info.bypass_all); 191 } 192 } 193 194 TEST_F(DataReductionProxyHeadersTest, HasDataReductionProxyViaHeader) { 195 const struct { 196 const char* headers; 197 bool expected_result; 198 } tests[] = { 199 { "HTTP/1.1 200 OK\n" 200 "Via: 1.1 Chrome-Proxy\n", 201 false, 202 }, 203 { "HTTP/1.1 200 OK\n" 204 "Via: 1\n", 205 false, 206 }, 207 { "HTTP/1.1 200 OK\n" 208 "Via: 1.1 Chrome-Compression-Proxy\n", 209 true, 210 }, 211 { "HTTP/1.1 200 OK\n" 212 "Via: 1.0 Chrome-Compression-Proxy\n", 213 true, 214 }, 215 { "HTTP/1.1 200 OK\n" 216 "Via: 1.1 Foo-Bar, 1.1 Chrome-Compression-Proxy\n", 217 true, 218 }, 219 { "HTTP/1.1 200 OK\n" 220 "Via: 1.1 Chrome-Compression-Proxy, 1.1 Bar-Foo\n", 221 true, 222 }, 223 { "HTTP/1.1 200 OK\n" 224 "Via: 1.1 chrome-compression-proxy\n", 225 false, 226 }, 227 { "HTTP/1.1 200 OK\n" 228 "Via: 1.1 Foo-Bar\n" 229 "Via: 1.1 Chrome-Compression-Proxy\n", 230 true, 231 }, 232 { "HTTP/1.1 200 OK\n" 233 "Via: 1.1 Chrome-Proxy\n", 234 false, 235 }, 236 { "HTTP/1.1 200 OK\n" 237 "Via: 1.1 Chrome Compression Proxy\n", 238 true, 239 }, 240 { "HTTP/1.1 200 OK\n" 241 "Via: 1.1 Foo-Bar, 1.1 Chrome Compression Proxy\n", 242 true, 243 }, 244 { "HTTP/1.1 200 OK\n" 245 "Via: 1.1 Chrome Compression Proxy, 1.1 Bar-Foo\n", 246 true, 247 }, 248 { "HTTP/1.1 200 OK\n" 249 "Via: 1.1 chrome compression proxy\n", 250 false, 251 }, 252 { "HTTP/1.1 200 OK\n" 253 "Via: 1.1 Foo-Bar\n" 254 "Via: 1.1 Chrome Compression Proxy\n", 255 true, 256 }, 257 }; 258 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 259 std::string headers(tests[i].headers); 260 HeadersToRaw(&headers); 261 scoped_refptr<net::HttpResponseHeaders> parsed( 262 new net::HttpResponseHeaders(headers)); 263 264 EXPECT_EQ(tests[i].expected_result, 265 HasDataReductionProxyViaHeader(parsed)); 266 } 267 } 268 269 TEST_F(DataReductionProxyHeadersTest, GetDataReductionProxyBypassEventType) { 270 const struct { 271 const char* headers; 272 net::ProxyService::DataReductionProxyBypassEventType expected_result; 273 } tests[] = { 274 { "HTTP/1.1 200 OK\n" 275 "Chrome-Proxy: bypass=0\n" 276 "Via: 1.1 Chrome-Compression-Proxy\n", 277 net::ProxyService::SHORT_BYPASS, 278 }, 279 { "HTTP/1.1 200 OK\n" 280 "Chrome-Proxy: bypass=1799\n" 281 "Via: 1.1 Chrome-Compression-Proxy\n", 282 net::ProxyService::SHORT_BYPASS, 283 }, 284 { "HTTP/1.1 200 OK\n" 285 "Chrome-Proxy: bypass=1800\n" 286 "Via: 1.1 Chrome-Compression-Proxy\n", 287 net::ProxyService::LONG_BYPASS, 288 }, 289 { "HTTP/1.1 500 Internal Server Error\n" 290 "Via: 1.1 Chrome-Compression-Proxy\n", 291 net::ProxyService::INTERNAL_SERVER_ERROR_BYPASS, 292 }, 293 { "HTTP/1.1 501 Not Implemented\n" 294 "Via: 1.1 Chrome-Compression-Proxy\n", 295 net::ProxyService::BYPASS_EVENT_TYPE_MAX, 296 }, 297 { "HTTP/1.1 502 Bad Gateway\n" 298 "Via: 1.1 Chrome-Compression-Proxy\n", 299 net::ProxyService::INTERNAL_SERVER_ERROR_BYPASS, 300 }, 301 { "HTTP/1.1 503 Service Unavailable\n" 302 "Via: 1.1 Chrome-Compression-Proxy\n", 303 net::ProxyService::INTERNAL_SERVER_ERROR_BYPASS, 304 }, 305 { "HTTP/1.1 504 Gateway Timeout\n" 306 "Via: 1.1 Chrome-Compression-Proxy\n", 307 net::ProxyService::BYPASS_EVENT_TYPE_MAX, 308 }, 309 { "HTTP/1.1 505 HTTP Version Not Supported\n" 310 "Via: 1.1 Chrome-Compression-Proxy\n", 311 net::ProxyService::BYPASS_EVENT_TYPE_MAX, 312 }, 313 { "HTTP/1.1 304 Not Modified\n", 314 net::ProxyService::BYPASS_EVENT_TYPE_MAX, 315 }, 316 { "HTTP/1.1 200 OK\n", 317 net::ProxyService::MISSING_VIA_HEADER, 318 }, 319 { "HTTP/1.1 200 OK\n" 320 "Chrome-Proxy: bypass=1799\n", 321 net::ProxyService::SHORT_BYPASS, 322 }, 323 { "HTTP/1.1 502 Bad Gateway\n", 324 net::ProxyService::INTERNAL_SERVER_ERROR_BYPASS, 325 }, 326 { "HTTP/1.1 502 Bad Gateway\n" 327 "Chrome-Proxy: bypass=1799\n", 328 net::ProxyService::SHORT_BYPASS, 329 }, 330 { "HTTP/1.1 502 Bad Gateway\n" 331 "Chrome-Proxy: bypass=1799\n", 332 net::ProxyService::SHORT_BYPASS, 333 }, 334 { "HTTP/1.1 414 Request-URI Too Long\n", 335 net::ProxyService::PROXY_4XX_BYPASS, 336 }, 337 { "HTTP/1.1 414 Request-URI Too Long\n" 338 "Via: 1.1 Chrome-Compression-Proxy\n", 339 net::ProxyService::BYPASS_EVENT_TYPE_MAX, 340 }, 341 { "HTTP/1.1 407 Proxy Authentication Required\n", 342 net::ProxyService::MALFORMED_407_BYPASS, 343 }, 344 { "HTTP/1.1 407 Proxy Authentication Required\n" 345 "Proxy-Authenticate: Basic\n" 346 "Via: 1.1 Chrome-Compression-Proxy\n", 347 net::ProxyService::BYPASS_EVENT_TYPE_MAX, 348 } 349 }; 350 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { 351 std::string headers(tests[i].headers); 352 HeadersToRaw(&headers); 353 scoped_refptr<net::HttpResponseHeaders> parsed( 354 new net::HttpResponseHeaders(headers)); 355 DataReductionProxyInfo chrome_proxy_info; 356 EXPECT_EQ(tests[i].expected_result, 357 GetDataReductionProxyBypassEventType(parsed, &chrome_proxy_info)); 358 } 359 } 360 } // namespace data_reduction_proxy 361