Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2015 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/test/embedded_test_server/request_helpers.h" | |
|
mmenke
2015/10/15 20:16:15
default_request_handlers?
svaldez
2015/10/15 21:04:32
Since the main purpose of this file when used by o
mmenke
2015/10/15 21:13:54
If you want shareable helper methods for consumers
| |
| 6 | |
| 7 #include <stdlib.h> | |
| 8 #include <ctime> | |
| 9 #include <map> | |
| 10 #include <sstream> | |
| 11 #include <string> | |
| 12 | |
| 13 #include "base/base64.h" | |
| 14 #include "base/files/file_path.h" | |
| 15 #include "base/files/file_util.h" | |
| 16 #include "base/format_macros.h" | |
| 17 #include "base/md5.h" | |
| 18 #include "base/path_service.h" | |
| 19 #include "base/strings/string_split.h" | |
| 20 #include "base/strings/string_util.h" | |
| 21 #include "base/strings/stringprintf.h" | |
| 22 #include "base/thread_task_runner_handle.h" | |
| 23 #include "base/threading/thread_restrictions.h" | |
| 24 #include "base/time/time.h" | |
| 25 #include "net/base/escape.h" | |
| 26 #include "net/base/url_util.h" | |
| 27 #include "net/test/embedded_test_server/embedded_test_server.h" | |
| 28 #include "net/test/embedded_test_server/http_request.h" | |
| 29 #include "net/test/embedded_test_server/http_response.h" | |
| 30 | |
| 31 #define NOT_HANDLED nullptr | |
|
mmenke
2015/10/15 19:38:18
This seems kinda weird and not really needed.
svaldez
2015/10/15 21:04:33
Done.
| |
| 32 | |
| 33 const net::UnescapeRule::Type kUnescapeAll = | |
| 34 net::UnescapeRule::SPACES | net::UnescapeRule::URL_SPECIAL_CHARS | | |
| 35 net::UnescapeRule::SPOOFING_AND_CONTROL_CHARS | | |
| 36 net::UnescapeRule::REPLACE_PLUS_WITH_SPACE; | |
|
mmenke
2015/10/15 19:38:17
Anonymous namespace, and move this down so you don
svaldez
2015/10/15 21:04:33
Done.
| |
| 37 | |
| 38 const std::string kDefaultRealm = "testrealm"; | |
| 39 const std::string kDefaultPassword = "password"; | |
|
mmenke
2015/10/15 19:38:17
const char[] (Only POD types can be globals, and S
svaldez
2015/10/15 21:04:34
Done.
| |
| 40 | |
| 41 namespace net { | |
| 42 namespace test_server { | |
| 43 | |
| 44 void CustomHttpResponse::SendResponse(SendBytesCallback send, | |
| 45 SendCompleteCallback done) { | |
| 46 std::string response; | |
| 47 if (headers_.size() != 0 || contents_.size() != 0) | |
| 48 response = headers_ + "\r\n" + contents_; | |
| 49 send.Run(response, done); | |
| 50 } | |
| 51 | |
| 52 bool ShouldHandle(const HttpRequest& request, std::string url) { | |
|
mmenke
2015/10/15 19:38:17
May want to build this into EmbeddedTestServer, as
mmenke
2015/10/15 19:38:18
|url| -> |path_prefix|
svaldez
2015/10/15 21:04:33
Done.
svaldez
2015/10/15 21:04:33
Done.
| |
| 53 if (request.relative_url.compare(0, url.size(), url) != 0) | |
| 54 return false; | |
| 55 std::string endings("/?;#"); | |
|
mmenke
2015/10/15 19:38:17
Not a fan of manually parsing URLs like this.
I s
svaldez
2015/10/15 21:04:33
Done.
| |
| 56 return request.relative_url.size() == url.size() || | |
| 57 endings.find(request.relative_url.at(url.size())) != std::string::npos; | |
| 58 } | |
| 59 | |
| 60 RequestQuery ParseQuery(const GURL& url) { | |
|
mmenke
2015/10/15 19:38:18
All this stuff that isn't exposed in the header sh
svaldez
2015/10/15 21:04:34
Done.
| |
| 61 RequestQuery queries; | |
| 62 | |
| 63 for (QueryIterator it(url); !it.IsAtEnd(); it.Advance()) { | |
| 64 queries[net::UnescapeURLComponent(it.GetKey(), kUnescapeAll)].push_back( | |
| 65 it.GetUnescapedValue()); | |
| 66 } | |
| 67 return queries; | |
| 68 } | |
| 69 | |
| 70 void GetFilePathWithReplacements(const std::string& original_file_path, | |
|
mmenke
2015/10/15 19:38:18
This needs documentation.
svaldez
2015/10/15 21:04:33
In the header.
| |
| 71 const base::StringPairs& text_to_replace, | |
| 72 std::string* replacement_path) { | |
|
mmenke
2015/10/15 19:38:17
Should just return a string (It's a little less ef
svaldez
2015/10/15 21:04:32
Maintaining compatibility with the STS version of
| |
| 73 std::string new_file_path = original_file_path; | |
| 74 bool first_query_parameter = true; | |
| 75 for (base::StringPairs::const_iterator it = text_to_replace.begin(); | |
| 76 it != text_to_replace.end(); ++it) { | |
|
mmenke
2015/10/15 19:38:18
Can you use a range loop here?
svaldez
2015/10/15 21:04:33
Done.
| |
| 77 const std::string& old_text = it->first; | |
| 78 const std::string& new_text = it->second; | |
| 79 std::string base64_old; | |
| 80 std::string base64_new; | |
| 81 base::Base64Encode(old_text, &base64_old); | |
| 82 base::Base64Encode(new_text, &base64_new); | |
| 83 if (first_query_parameter) { | |
| 84 new_file_path += "?"; | |
| 85 first_query_parameter = false; | |
| 86 } else { | |
| 87 new_file_path += "&"; | |
| 88 } | |
| 89 new_file_path += "replace_text="; | |
| 90 new_file_path += base64_old; | |
| 91 new_file_path += ":"; | |
| 92 new_file_path += base64_new; | |
| 93 } | |
| 94 | |
| 95 *replacement_path = new_file_path; | |
| 96 } | |
| 97 | |
| 98 GURL ToGURL(const HttpRequest& request) { | |
| 99 return GURL("http://localhost" + request.relative_url); | |
|
mmenke
2015/10/15 19:38:17
Suggest making this a member of HttpRequest (And u
svaldez
2015/10/15 21:04:32
Done.
| |
| 100 } | |
| 101 | |
| 102 // Handles |request| by serving a file from under |server_root|. | |
| 103 scoped_ptr<HttpResponse> HandleFileRequest(const base::FilePath& server_root, | |
| 104 const HttpRequest& request) { | |
| 105 // This is a test-only server. Ignore I/O thread restrictions. | |
| 106 base::ThreadRestrictions::ScopedAllowIO allow_io; | |
|
mmenke
2015/10/15 19:38:18
Is this needed? We're running on our private thre
svaldez
2015/10/15 21:04:33
Still required since the restriction is only on th
| |
| 107 | |
| 108 std::string relative_url(request.relative_url); | |
| 109 | |
| 110 // A proxy request will have an absolute path. Simulate the proxy by stripping | |
| 111 // the scheme, host, and port. | |
| 112 GURL request_gurl = ToGURL(request); | |
| 113 relative_url = request_gurl.path(); | |
| 114 | |
| 115 std::string files_prefix("/files/"); | |
|
mmenke
2015/10/15 19:38:17
I thought you said you weren't doing this?
svaldez
2015/10/15 21:04:33
Yeah, I was using it to find any remaining old-sty
| |
| 116 if (relative_url.compare(0, files_prefix.size(), files_prefix) == 0) { | |
| 117 LOG(ERROR) << "Using old-style /files/ for: " << relative_url; | |
| 118 relative_url = relative_url.substr(files_prefix.size() - 1); | |
| 119 } | |
| 120 | |
| 121 std::string post_prefix("/post/"); | |
| 122 if (relative_url.compare(0, post_prefix.size(), post_prefix) == 0) { | |
| 123 relative_url = relative_url.substr(post_prefix.size() - 1); | |
| 124 if (request.method != METHOD_POST) | |
| 125 return NOT_HANDLED; | |
| 126 } | |
| 127 | |
| 128 RequestQuery query = ParseQuery(request_gurl); | |
| 129 | |
| 130 if (query.find("expected_body") != query.end()) { | |
| 131 if (request.content.find(query["expected_body"].front()) == | |
|
mmenke
2015/10/15 19:38:18
base::StartsWithASCII? I don't think I've ever se
svaldez
2015/10/15 21:04:33
Is there a version for "containsASCII"?
mmenke
2015/10/15 21:13:54
Oops...That comment was meant to go below the "/po
| |
| 132 std::string::npos) { | |
| 133 scoped_ptr<BasicHttpResponse> not_found_response(new BasicHttpResponse); | |
| 134 not_found_response->set_code(HTTP_NOT_FOUND); | |
| 135 return not_found_response.Pass(); | |
| 136 } | |
| 137 } | |
| 138 | |
| 139 if (query.find("expected_headers") != query.end()) { | |
| 140 std::vector<std::string> headers = query["expected_headers"]; | |
| 141 for (std::vector<std::string>::iterator it = headers.begin(); | |
| 142 it != headers.end(); ++it) { | |
|
mmenke
2015/10/15 19:38:17
Range loop? (And can then just inline query["expe
svaldez
2015/10/15 21:04:33
Done.
| |
| 143 std::string key = it->substr(0, it->find(":")); | |
| 144 std::string value = it->substr(it->find(":") + 1); | |
|
mmenke
2015/10/15 19:38:17
Should probably just explicitly fail when there is
svaldez
2015/10/15 21:04:33
Done.
| |
| 145 if (request.headers.find(key) == request.headers.end() || | |
| 146 request.headers.at(key) != value) { | |
| 147 scoped_ptr<BasicHttpResponse> not_found_response(new BasicHttpResponse); | |
| 148 not_found_response->set_code(HTTP_NOT_FOUND); | |
| 149 return not_found_response.Pass(); | |
| 150 } | |
| 151 } | |
| 152 } | |
| 153 | |
| 154 // Trim the first byte ('/'). | |
| 155 std::string request_path = relative_url.substr(1); | |
| 156 base::FilePath file_path(server_root.AppendASCII(request_path)); | |
| 157 std::string file_contents; | |
| 158 if (!base::ReadFileToString(file_path, &file_contents)) { | |
| 159 file_path = file_path.AppendASCII("index.html"); | |
| 160 if (!base::ReadFileToString(file_path, &file_contents)) | |
| 161 return NOT_HANDLED; | |
|
mmenke
2015/10/15 19:38:17
Should we return an error if there was a files/ or
svaldez
2015/10/15 21:04:33
Could be that there is another File handler that m
mmenke
2015/10/15 21:13:54
But there isn't...files/ was removed anyways, now,
| |
| 162 } | |
| 163 | |
| 164 if (query.find("replace_text") != query.end()) { | |
| 165 std::vector<std::string> replacements = query["replace_text"]; | |
| 166 for (std::vector<std::string>::iterator it = replacements.begin(); | |
| 167 it != replacements.end(); ++it) { | |
|
mmenke
2015/10/15 19:38:17
Range loop
svaldez
2015/10/15 21:04:33
Done.
| |
| 168 std::string find, with; | |
|
mmenke
2015/10/15 19:38:18
Only declare one variable per line.
svaldez
2015/10/15 21:04:33
Done.
| |
| 169 base::Base64Decode(it->substr(0, it->find(":")), &find); | |
| 170 base::Base64Decode(it->substr(it->find(":") + 1), &with); | |
| 171 base::ReplaceSubstringsAfterOffset(&file_contents, 0, find, with); | |
| 172 } | |
| 173 } | |
| 174 | |
| 175 base::FilePath headers_path( | |
| 176 file_path.AddExtension(FILE_PATH_LITERAL("mock-http-headers"))); | |
| 177 | |
| 178 if (base::PathExists(headers_path)) { | |
| 179 std::string headers_contents; | |
| 180 | |
| 181 if (!base::ReadFileToString(headers_path, &headers_contents)) | |
| 182 return NOT_HANDLED; | |
|
mmenke
2015/10/15 19:38:17
Should we return an error in this case?
svaldez
2015/10/15 21:04:32
The way its currently implemented in STS only retu
| |
| 183 | |
| 184 if (request.method == METHOD_HEAD) | |
| 185 file_contents = ""; | |
|
mmenke
2015/10/15 19:38:17
Should we be doing this regardless of the presence
svaldez
2015/10/15 21:04:33
Done.
| |
| 186 | |
| 187 scoped_ptr<CustomHttpResponse> http_response( | |
| 188 new CustomHttpResponse(headers_contents, file_contents)); | |
| 189 return http_response.Pass(); | |
| 190 } | |
| 191 | |
| 192 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 193 http_response->set_code(HTTP_OK); | |
| 194 | |
| 195 if (request.headers.find("Range") != request.headers.end()) { | |
| 196 std::string range_header = request.headers.at("Range"); | |
| 197 if (range_header.compare(0, 6, "bytes=") == 0) { | |
|
mmenke
2015/10/15 19:38:18
HttpUtil::ParseRangeHeader?
svaldez
2015/10/15 21:04:33
Done.
| |
| 198 range_header = range_header.substr(6); | |
| 199 | |
| 200 size_t start = 0; | |
| 201 size_t end = file_contents.size(); | |
| 202 size_t delim = range_header.find("-"); | |
| 203 | |
| 204 if (delim == std::string::npos) { | |
| 205 start = std::atoi(range_header.c_str()); | |
| 206 } else if (delim == range_header.size() - 1) { | |
| 207 start = std::atoi(range_header.substr(0, delim).c_str()); | |
| 208 } else if (delim == 0) { | |
| 209 start = end - std::atoi(range_header.substr(1).c_str()); | |
| 210 } else { | |
| 211 start = std::atoi(range_header.substr(0, delim).c_str()); | |
| 212 end = std::atoi(range_header.substr(delim + 1).c_str()); | |
| 213 } | |
| 214 | |
| 215 http_response->set_code(HTTP_PARTIAL_CONTENT); | |
| 216 http_response->AddCustomHeader( | |
| 217 "Content-Range", | |
| 218 base::StringPrintf("bytes %" PRIuS "-%" PRIuS "/%" PRIuS, start, | |
| 219 end - 1, file_contents.size())); | |
| 220 | |
| 221 file_contents = file_contents.substr(start, end - start); | |
| 222 } | |
| 223 } | |
| 224 | |
| 225 if (file_path.MatchesExtension(FILE_PATH_LITERAL(".crx"))) | |
| 226 http_response->set_content_type("application/x-chrome-extension"); | |
| 227 else if (file_path.MatchesExtension(FILE_PATH_LITERAL(".exe"))) | |
| 228 http_response->set_content_type("application/octet-stream"); | |
| 229 else if (file_path.MatchesExtension(FILE_PATH_LITERAL(".gif"))) | |
| 230 http_response->set_content_type("image/gif"); | |
| 231 else if (file_path.MatchesExtension(FILE_PATH_LITERAL(".jpeg")) || | |
| 232 file_path.MatchesExtension(FILE_PATH_LITERAL(".jpg"))) | |
| 233 http_response->set_content_type("image/jpeg"); | |
| 234 else if (file_path.MatchesExtension(FILE_PATH_LITERAL(".js"))) | |
| 235 http_response->set_content_type("application/javascript"); | |
| 236 else if (file_path.MatchesExtension(FILE_PATH_LITERAL(".json"))) | |
| 237 http_response->set_content_type("application/json"); | |
| 238 else if (file_path.MatchesExtension(FILE_PATH_LITERAL(".pdf"))) | |
| 239 http_response->set_content_type("application/pdf"); | |
| 240 else if (file_path.MatchesExtension(FILE_PATH_LITERAL(".txt"))) | |
| 241 http_response->set_content_type("text/plain"); | |
| 242 else if (file_path.MatchesExtension(FILE_PATH_LITERAL(".wav"))) | |
| 243 http_response->set_content_type("audio/wav"); | |
| 244 else if (file_path.MatchesExtension(FILE_PATH_LITERAL(".xml"))) | |
| 245 http_response->set_content_type("text/xml"); | |
| 246 else if (file_path.MatchesExtension(FILE_PATH_LITERAL(".html")) || | |
| 247 file_path.MatchesExtension(FILE_PATH_LITERAL(".htm"))) | |
| 248 http_response->set_content_type("text/html"); | |
|
mmenke
2015/10/15 19:38:17
Think all this should be in a separate method.
svaldez
2015/10/15 21:04:33
Done.
| |
| 249 | |
| 250 http_response->AddCustomHeader("Accept-Ranges", "bytes"); | |
| 251 http_response->AddCustomHeader("ETag", "'" + file_path.MaybeAsASCII() + "'"); | |
| 252 http_response->set_content(file_contents); | |
| 253 return http_response.Pass(); | |
| 254 } | |
| 255 | |
| 256 scoped_ptr<HttpResponse> HandleRedirectConnect(const HttpRequest& request) { | |
| 257 if (request.headers.find("Host") == request.headers.end() || | |
| 258 request.headers.at("Host") != "www.redirect.com" || | |
| 259 request.method != METHOD_CONNECT) | |
| 260 return NOT_HANDLED; | |
|
mmenke
2015/10/15 19:38:18
nit: Use braces
svaldez
2015/10/15 21:04:33
Done.
| |
| 261 | |
| 262 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 263 http_response->set_code(HTTP_FOUND); | |
| 264 http_response->AddCustomHeader("Location", | |
| 265 "http://www.destination.com/foo.js"); | |
| 266 return http_response.Pass(); | |
| 267 } | |
| 268 | |
| 269 scoped_ptr<HttpResponse> HandleServerAuthConnect(const HttpRequest& request) { | |
| 270 if (request.headers.find("Host") == request.headers.end() || | |
| 271 request.headers.at("Host") != "www.server-auth.com" || | |
| 272 request.method != METHOD_CONNECT) | |
| 273 return NOT_HANDLED; | |
|
mmenke
2015/10/15 19:38:18
nit: Braces
svaldez
2015/10/15 21:04:33
Done.
| |
| 274 | |
| 275 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 276 http_response->set_code(HTTP_UNAUTHORIZED); | |
| 277 http_response->AddCustomHeader("WWW-Authenticate", | |
| 278 "Basic realm=\"WallyWorld\""); | |
| 279 return http_response.Pass(); | |
| 280 } | |
| 281 | |
| 282 scoped_ptr<HttpResponse> HandleDefaultConnect(const HttpRequest& request) { | |
| 283 if (request.method != METHOD_CONNECT) | |
| 284 return NOT_HANDLED; | |
| 285 | |
| 286 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 287 http_response->set_code(HTTP_BAD_REQUEST); | |
| 288 http_response->set_content( | |
| 289 "Your client has issued a malformed or illegal request."); | |
| 290 http_response->set_content_type("text/html"); | |
| 291 return http_response.Pass(); | |
| 292 } | |
| 293 | |
| 294 scoped_ptr<HttpResponse> HandleCacheControl(std::string url, | |
|
mmenke
2015/10/15 19:38:17
All of these should be const std::string &
svaldez
2015/10/15 21:04:33
Acknowledged.
| |
| 295 std::string value, | |
|
mmenke
2015/10/15 19:38:18
Should use a clearer name than "value"
svaldez
2015/10/15 21:04:33
Acknowledged.
| |
| 296 const HttpRequest& request) { | |
| 297 if (!ShouldHandle(request, url)) | |
| 298 return NOT_HANDLED; | |
| 299 | |
| 300 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 301 http_response->set_code(HTTP_OK); | |
| 302 std::stringstream time; | |
| 303 time << std::time(0); | |
|
mmenke
2015/10/15 19:38:17
Suggest using base::Time
svaldez
2015/10/15 21:04:34
Acknowledged.
| |
| 304 http_response->set_content("<html><head><title>" + time.str() + | |
| 305 "</title></head></html>"); | |
|
mmenke
2015/10/15 19:38:17
Hrm...I wonder about the utility of all of these -
svaldez
2015/10/15 21:04:33
Acknowledged.
| |
| 306 http_response->set_content_type("text/html"); | |
| 307 http_response->AddCustomHeader("Cache-Control", value); | |
| 308 return http_response.Pass(); | |
| 309 } | |
| 310 | |
| 311 scoped_ptr<HttpResponse> HandleCacheExpires(const HttpRequest& request) { | |
| 312 if (!ShouldHandle(request, "/cache/expires")) | |
| 313 return NOT_HANDLED; | |
| 314 | |
| 315 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 316 http_response->set_code(HTTP_OK); | |
| 317 std::stringstream time; | |
| 318 time << std::time(0); | |
| 319 http_response->set_content("<html><head><title>" + time.str() + | |
| 320 "</title></head></html>"); | |
| 321 http_response->set_content_type("text/html"); | |
| 322 http_response->AddCustomHeader("Expires", "Thu, 1 Jan 2099 00:00:00 GMT"); | |
| 323 return http_response.Pass(); | |
| 324 } | |
| 325 | |
| 326 scoped_ptr<HttpResponse> HandleEchoHeader(std::string url, | |
| 327 std::string value, | |
| 328 const HttpRequest& request) { | |
| 329 if (!ShouldHandle(request, url)) | |
| 330 return NOT_HANDLED; | |
| 331 | |
| 332 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 333 http_response->set_code(HTTP_OK); | |
| 334 | |
| 335 GURL request_gurl = ToGURL(request); | |
| 336 if (request_gurl.has_query()) { | |
| 337 std::string header_name = request_gurl.query(); | |
| 338 http_response->AddCustomHeader("Vary", header_name); | |
| 339 if (request.headers.find(header_name) != request.headers.end()) | |
| 340 http_response->set_content(request.headers.at(header_name)); | |
| 341 else | |
| 342 http_response->set_content("None"); | |
| 343 } | |
| 344 | |
| 345 http_response->set_content_type("text/plain"); | |
| 346 http_response->AddCustomHeader("Cache-Control", value); | |
| 347 return http_response.Pass(); | |
| 348 } | |
| 349 | |
| 350 scoped_ptr<HttpResponse> HandleEcho(const HttpRequest& request) { | |
| 351 if (!ShouldHandle(request, "/echo")) | |
|
mmenke
2015/10/15 19:38:17
Think all of the ones based on path should use a w
svaldez
2015/10/15 21:04:33
Done.
| |
| 352 return NOT_HANDLED; | |
| 353 | |
| 354 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 355 http_response->set_code(HTTP_OK); | |
| 356 | |
| 357 GURL request_gurl = ToGURL(request); | |
| 358 if (request_gurl.has_query()) { | |
| 359 RequestQuery query = ParseQuery(request_gurl); | |
| 360 if (query.find("status") != query.end()) | |
| 361 http_response->set_code(static_cast<HttpStatusCode>( | |
| 362 std::atoi(query["status"].front().c_str()))); | |
| 363 } | |
| 364 | |
| 365 http_response->set_content_type("text/html"); | |
| 366 if (request.method != METHOD_POST && request.method != METHOD_PUT) | |
| 367 http_response->set_content("Echo"); | |
| 368 else | |
| 369 http_response->set_content(request.content); | |
| 370 return http_response.Pass(); | |
| 371 } | |
| 372 | |
| 373 scoped_ptr<HttpResponse> HandleEchoTitle(const HttpRequest& request) { | |
| 374 if (!ShouldHandle(request, "/echotitle")) | |
| 375 return NOT_HANDLED; | |
| 376 | |
| 377 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 378 http_response->set_code(HTTP_OK); | |
| 379 http_response->set_content_type("text/html"); | |
| 380 http_response->set_content("<html><head><title>" + request.content + | |
| 381 "</title></head></html>"); | |
| 382 return http_response.Pass(); | |
| 383 } | |
| 384 | |
| 385 scoped_ptr<HttpResponse> HandleEchoAll(const HttpRequest& request) { | |
| 386 if (!ShouldHandle(request, "/echoall")) | |
| 387 return NOT_HANDLED; | |
| 388 | |
| 389 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 390 http_response->set_code(HTTP_OK); | |
| 391 | |
| 392 std::string body; | |
| 393 body += | |
| 394 "<html><head><style>" | |
| 395 "pre { border: 1px solid black; margin: 5px; padding: 5px }" | |
| 396 "</style></head><body>" | |
| 397 "<div style=\"float: right\">" | |
| 398 "<a href=\"/echo\">back to referring page</a></div>" | |
| 399 "<h1>Request Body:</h1><pre>"; | |
| 400 | |
| 401 if (request.has_content) { | |
| 402 std::vector<std::string> qs = base::SplitString( | |
| 403 request.content, "&", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); | |
| 404 for (size_t i = 0; i < qs.size(); ++i) { | |
| 405 body += qs[i] + "\n"; | |
| 406 } | |
| 407 } | |
| 408 | |
| 409 body += | |
| 410 "</pre>" | |
| 411 "<h1>Request Headers:</h1><pre>" + | |
| 412 request.all_headers + | |
| 413 "</pre>" | |
| 414 "</body></html>"; | |
| 415 | |
| 416 http_response->set_content_type("text/html"); | |
| 417 http_response->set_content(body); | |
| 418 return http_response.Pass(); | |
| 419 } | |
| 420 | |
| 421 scoped_ptr<HttpResponse> HandleSetCookie(const HttpRequest& request) { | |
| 422 if (!ShouldHandle(request, "/set-cookie")) | |
| 423 return NOT_HANDLED; | |
| 424 | |
| 425 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 426 http_response->set_code(HTTP_OK); | |
| 427 http_response->set_content_type("text/html"); | |
| 428 std::string content; | |
| 429 GURL request_gurl = ToGURL(request); | |
| 430 if (request_gurl.has_query()) { | |
| 431 std::vector<std::string> cookies = base::SplitString( | |
| 432 request_gurl.query(), "&", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); | |
| 433 for (size_t i = 0; i < cookies.size(); ++i) { | |
| 434 http_response->AddCustomHeader("Set-Cookie", cookies[i]); | |
| 435 content += cookies[i]; | |
| 436 } | |
| 437 } | |
| 438 | |
| 439 http_response->set_content(content); | |
| 440 return http_response.Pass(); | |
| 441 } | |
| 442 | |
| 443 scoped_ptr<HttpResponse> HandleSetManyCookies(const HttpRequest& request) { | |
| 444 if (!ShouldHandle(request, "/set-many-cookies")) | |
| 445 return NOT_HANDLED; | |
| 446 | |
| 447 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 448 http_response->set_code(HTTP_OK); | |
| 449 http_response->set_content_type("text/html"); | |
| 450 std::string content; | |
| 451 | |
| 452 GURL request_gurl = ToGURL(request); | |
| 453 size_t num = 0; | |
| 454 if (request_gurl.has_query()) { | |
| 455 num = std::atoi(request_gurl.query().c_str()); | |
| 456 } | |
| 457 | |
| 458 for (size_t i = 0; i < num; ++i) { | |
| 459 http_response->AddCustomHeader("Set-Cookie", "a="); | |
| 460 } | |
| 461 | |
| 462 http_response->set_content( | |
| 463 base::StringPrintf("%" PRIuS " cookies were sent", num)); | |
| 464 return http_response.Pass(); | |
| 465 } | |
| 466 | |
| 467 scoped_ptr<HttpResponse> HandleExpectAndSetCookie(const HttpRequest& request) { | |
| 468 if (!ShouldHandle(request, "/expect-and-set-cookie")) | |
| 469 return NOT_HANDLED; | |
| 470 | |
| 471 std::vector<std::string> sentCookies; | |
| 472 if (request.headers.find("Cookie") != request.headers.end()) { | |
| 473 std::vector<std::string> cookies = | |
| 474 base::SplitString(request.headers.at("Cookie"), ";", | |
| 475 base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); | |
| 476 for (size_t i = 0; i < cookies.size(); ++i) { | |
| 477 sentCookies.push_back(cookies[i]); | |
| 478 } | |
| 479 } | |
| 480 bool gotExpected = true; | |
| 481 | |
| 482 GURL request_gurl = ToGURL(request); | |
| 483 RequestQuery qs = ParseQuery(request_gurl); | |
| 484 if (qs.find("expect") != qs.end()) { | |
| 485 std::vector<std::string> expected = qs.at("expect"); | |
| 486 for (size_t i = 0; i < expected.size(); ++i) { | |
| 487 bool found = false; | |
| 488 for (size_t j = 0; j < sentCookies.size(); ++j) { | |
| 489 if (expected[i] == sentCookies[j]) | |
| 490 found = true; | |
| 491 } | |
| 492 gotExpected &= found; | |
| 493 } | |
| 494 } | |
| 495 | |
| 496 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 497 http_response->set_code(HTTP_OK); | |
| 498 http_response->set_content_type("text/html"); | |
| 499 if (gotExpected) { | |
| 500 std::vector<std::string> setCookies = qs.at("set"); | |
| 501 for (size_t i = 0; i < setCookies.size(); ++i) { | |
| 502 http_response->AddCustomHeader( | |
| 503 "Set-Cookie", net::UnescapeURLComponent(setCookies[i], kUnescapeAll)); | |
| 504 } | |
| 505 } | |
| 506 | |
| 507 std::string content; | |
| 508 if (qs.find("data") != qs.end()) { | |
| 509 std::vector<std::string> data = qs.at("data"); | |
| 510 for (size_t i = 0; i < data.size(); ++i) { | |
| 511 content += data[i]; | |
| 512 } | |
| 513 } | |
| 514 | |
| 515 http_response->set_content(content); | |
| 516 return http_response.Pass(); | |
| 517 } | |
| 518 | |
| 519 scoped_ptr<HttpResponse> HandleSetHeader(const HttpRequest& request) { | |
| 520 if (!ShouldHandle(request, "/set-header")) | |
| 521 return NOT_HANDLED; | |
| 522 | |
| 523 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 524 http_response->set_code(HTTP_OK); | |
| 525 http_response->set_content_type("text/html"); | |
| 526 | |
| 527 std::string content; | |
| 528 | |
| 529 GURL request_gurl = ToGURL(request); | |
| 530 if (request_gurl.has_query()) { | |
| 531 RequestQuery headers = ParseQuery(request_gurl); | |
| 532 for (RequestQuery::iterator it = headers.begin(); it != headers.end(); | |
| 533 ++it) { | |
| 534 std::string header = it->first; | |
| 535 std::string key = header.substr(0, header.find(": ")); | |
| 536 std::string value = header.substr(header.find(": ") + 2); | |
| 537 http_response->AddCustomHeader(key, value); | |
| 538 content += header; | |
| 539 } | |
| 540 } | |
| 541 | |
| 542 http_response->set_content(content); | |
| 543 return http_response.Pass(); | |
| 544 } | |
| 545 | |
| 546 scoped_ptr<HttpResponse> HandleNoContent(const HttpRequest& request) { | |
| 547 if (!ShouldHandle(request, "/nocontent")) | |
| 548 return NOT_HANDLED; | |
| 549 | |
| 550 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 551 http_response->set_code(HTTP_NO_CONTENT); | |
| 552 return http_response.Pass(); | |
| 553 } | |
| 554 | |
| 555 scoped_ptr<HttpResponse> HandleCloseSocket(const HttpRequest& request) { | |
| 556 if (!ShouldHandle(request, "/close-socket")) | |
| 557 return NOT_HANDLED; | |
| 558 | |
| 559 scoped_ptr<CustomHttpResponse> http_response(new CustomHttpResponse("", "")); | |
| 560 return http_response.Pass(); | |
| 561 } | |
| 562 | |
| 563 scoped_ptr<HttpResponse> HandleAuthBasic(const HttpRequest& request) { | |
| 564 if (!ShouldHandle(request, "/auth-basic")) | |
| 565 return NOT_HANDLED; | |
| 566 | |
| 567 GURL request_gurl = ToGURL(request); | |
| 568 RequestQuery query = ParseQuery(request_gurl); | |
| 569 | |
| 570 std::string expectedPassword = "secret"; | |
| 571 if (query.find(kDefaultPassword) != query.end()) | |
| 572 expectedPassword = query.at(kDefaultPassword).front(); | |
| 573 std::string realm = kDefaultRealm; | |
| 574 if (query.find("realm") != query.end()) | |
| 575 realm = query.at("realm").front(); | |
| 576 | |
| 577 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 578 bool authed = false; | |
| 579 std::string error; | |
| 580 std::string auth; | |
| 581 std::string username; | |
| 582 std::string userpass; | |
| 583 std::string password; | |
| 584 std::string b64str; | |
| 585 if (request.headers.find("Authorization") == request.headers.end()) { | |
| 586 error = "Missing Authorization Header"; | |
| 587 } else { | |
| 588 auth = request.headers.at("Authorization"); | |
| 589 if (auth.find("Basic ") == std::string::npos) { | |
| 590 error = "Invalid Authorization Header"; | |
| 591 } else { | |
| 592 b64str = auth.substr(std::string("Basic ").size()); | |
| 593 base::Base64Decode(b64str, &userpass); | |
| 594 if (userpass.find(":") != std::string::npos) { | |
| 595 username = userpass.substr(0, userpass.find(":")); | |
| 596 password = userpass.substr(userpass.find(":") + 1); | |
| 597 if (password == expectedPassword) | |
| 598 authed = true; | |
| 599 else | |
| 600 error = "Invalid Credentials"; | |
| 601 } else | |
| 602 error = "Invalid Credentials"; | |
| 603 } | |
| 604 } | |
| 605 | |
| 606 if (!authed) { | |
| 607 http_response->set_code(HTTP_UNAUTHORIZED); | |
| 608 http_response->set_content_type("text/html"); | |
| 609 http_response->AddCustomHeader("WWW-Authenticate", | |
| 610 "Basic realm=\"" + realm + "\""); | |
| 611 if (query.find("set-cookie-if-challenged") != query.end()) | |
| 612 http_response->AddCustomHeader("Set-Cookie", "got_challenged=true"); | |
| 613 http_response->set_content(base::StringPrintf( | |
| 614 "<html><head><title>Denied: %s</title></head>" | |
| 615 "<body>auth=%s<p>b64str=%s<p>username: %s<p>userpass: %s<p>" | |
| 616 "password: %s<p>You sent:<br>%s<p></body></html>", | |
| 617 error.c_str(), auth.c_str(), b64str.c_str(), username.c_str(), | |
| 618 userpass.c_str(), password.c_str(), request.all_headers.c_str())); | |
| 619 return http_response.Pass(); | |
| 620 } | |
| 621 | |
| 622 if (request.headers.find("If-None-Match") != request.headers.end() && | |
| 623 request.headers.at("If-None-Match") == "abc") { | |
| 624 http_response->set_code(HTTP_NOT_MODIFIED); | |
| 625 return http_response.Pass(); | |
| 626 } | |
| 627 | |
| 628 base::FilePath file_path = | |
| 629 base::FilePath().AppendASCII(request.relative_url.substr(1)); | |
| 630 if (file_path.FinalExtension() == FILE_PATH_LITERAL("gif")) { | |
| 631 base::FilePath server_root; | |
| 632 PathService::Get(base::DIR_SOURCE_ROOT, &server_root); | |
| 633 base::FilePath gif_path = | |
| 634 server_root.AppendASCII("chrome/test/data/google/logo.gif"); | |
| 635 std::string gif_data; | |
| 636 base::ReadFileToString(gif_path, &gif_data); | |
| 637 http_response->set_content_type("image/gif"); | |
| 638 http_response->set_content(gif_data); | |
| 639 } else { | |
| 640 http_response->set_content_type("text/html"); | |
| 641 http_response->set_content( | |
| 642 base::StringPrintf("<html><head><title>%s/%s</title></head>" | |
| 643 "<body>auth=%s<p>You sent:<br>%s<p></body></html>", | |
| 644 username.c_str(), password.c_str(), auth.c_str(), | |
| 645 request.all_headers.c_str())); | |
| 646 } | |
| 647 | |
| 648 http_response->set_code(HTTP_OK); | |
| 649 http_response->AddCustomHeader("Cache-Control", "max-age=60000"); | |
| 650 http_response->AddCustomHeader("Etag", "abc"); | |
| 651 return http_response.Pass(); | |
| 652 } | |
| 653 | |
| 654 scoped_ptr<HttpResponse> HandleAuthDigest(const HttpRequest& request) { | |
| 655 if (!ShouldHandle(request, "/auth-digest")) | |
| 656 return NOT_HANDLED; | |
| 657 | |
| 658 std::string nonce = base::MD5String( | |
| 659 base::StringPrintf("privatekey%s", request.relative_url.c_str())); | |
| 660 std::string opaque = base::MD5String("opaque"); | |
| 661 std::string password = "secret"; | |
| 662 std::string realm = kDefaultRealm; | |
| 663 | |
| 664 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 665 bool authed = false; | |
| 666 std::string error; | |
| 667 std::string auth; | |
| 668 std::string digestStr = "Digest"; | |
| 669 std::string username; | |
| 670 if (request.headers.find("Authorization") == request.headers.end()) { | |
| 671 error = "no auth"; | |
| 672 } else if (request.headers.at("Authorization").substr(0, digestStr.size()) != | |
| 673 digestStr) { | |
| 674 error = "not digest"; | |
| 675 } else { | |
| 676 auth = request.headers.at("Authorization"); | |
| 677 | |
| 678 std::map<std::string, std::string> authPairs; | |
| 679 std::vector<std::string> authVector = base::SplitString( | |
| 680 auth, ", ", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); | |
| 681 for (std::vector<std::string>::iterator it = authVector.begin(); | |
| 682 it != authVector.end(); ++it) { | |
| 683 std::string key = it->substr(0, it->find("=")); | |
| 684 std::string value = it->substr(it->find("=") + 1); | |
| 685 if (value.substr(0, 1) == "\"" && value.substr(value.size() - 1) == "\"") | |
| 686 value = value.substr(1, value.size() - 2); | |
| 687 authPairs[key] = value; | |
| 688 } | |
| 689 | |
| 690 if (authPairs["nonce"] != nonce) { | |
| 691 error = "wrong nonce"; | |
| 692 } else if (authPairs["opaque"] != opaque) { | |
| 693 error = "wrong opaque"; | |
| 694 } else { | |
| 695 username = authPairs["username"]; | |
| 696 | |
| 697 std::string hash1 = base::MD5String( | |
| 698 base::StringPrintf("%s:%s:%s", authPairs["username"].c_str(), | |
| 699 realm.c_str(), password.c_str())); | |
| 700 std::string hash2 = base::MD5String(base::StringPrintf( | |
| 701 "%s:%s", request.method_string.c_str(), authPairs["uri"].c_str())); | |
| 702 | |
| 703 std::string response; | |
| 704 if (authPairs.find("qop") != authPairs.end() && | |
| 705 authPairs.find("nc") != authPairs.end() && | |
| 706 authPairs.find("cnonce") != authPairs.end()) { | |
| 707 response = base::MD5String(base::StringPrintf( | |
| 708 "%s:%s:%s:%s:%s:%s", hash1.c_str(), nonce.c_str(), | |
| 709 authPairs["nc"].c_str(), authPairs["cnonce"].c_str(), | |
| 710 authPairs["qop"].c_str(), hash2.c_str())); | |
| 711 } else { | |
| 712 response = base::MD5String(base::StringPrintf( | |
| 713 "%s:%s:%s", hash1.c_str(), nonce.c_str(), hash2.c_str())); | |
| 714 } | |
| 715 | |
| 716 if (authPairs["response"] == response) | |
| 717 authed = true; | |
| 718 else | |
| 719 error = "wrong password"; | |
| 720 } | |
| 721 } | |
| 722 | |
| 723 if (!authed) { | |
| 724 http_response->set_code(HTTP_UNAUTHORIZED); | |
| 725 http_response->set_content_type("text/html"); | |
| 726 std::string authHeader = base::StringPrintf( | |
| 727 "Digest realm=\"%s\", " | |
| 728 "domain=\"/\", qop=\"auth\", algorithm=MD5, nonce=\"%s\", " | |
| 729 "opaque=\"%s\"", | |
| 730 realm.c_str(), nonce.c_str(), opaque.c_str()); | |
| 731 http_response->AddCustomHeader("WWW-Authenticate", authHeader); | |
| 732 http_response->set_content(base::StringPrintf( | |
| 733 "<html><head><title>Denied: %s</title></head>" | |
| 734 "<body>auth=%s<p>" | |
| 735 "You sent:<br>%s<p>We are replying:<br>%s<p></body></html>", | |
| 736 error.c_str(), auth.c_str(), request.all_headers.c_str(), | |
| 737 authHeader.c_str())); | |
| 738 return http_response.Pass(); | |
| 739 } | |
| 740 | |
| 741 http_response->set_content_type("text/html"); | |
| 742 http_response->set_content( | |
| 743 base::StringPrintf("<html><head><title>%s/%s</title></head>" | |
| 744 "<body>auth=%s<p></body></html>", | |
| 745 username.c_str(), password.c_str(), auth.c_str())); | |
| 746 | |
| 747 return http_response.Pass(); | |
| 748 } | |
| 749 | |
| 750 scoped_ptr<HttpResponse> HandleServerRedirect(const HttpRequest& request) { | |
| 751 if (!ShouldHandle(request, "/server-redirect")) | |
| 752 return NOT_HANDLED; | |
| 753 | |
| 754 GURL request_gurl = ToGURL(request); | |
| 755 std::string dest = | |
| 756 net::UnescapeURLComponent(request_gurl.query(), kUnescapeAll); | |
| 757 | |
| 758 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 759 http_response->set_code(HTTP_MOVED_PERMANENTLY); | |
| 760 http_response->AddCustomHeader("Location", dest); | |
| 761 http_response->set_content_type("text/html"); | |
| 762 http_response->set_content(base::StringPrintf( | |
| 763 "<html><head></head><body>Redirecting to %s</body></html>", | |
| 764 dest.c_str())); | |
| 765 return http_response.Pass(); | |
| 766 } | |
| 767 | |
| 768 scoped_ptr<HttpResponse> HandleCrossSiteRedirect(EmbeddedTestServer* server, | |
| 769 const HttpRequest& request) { | |
| 770 if (!ShouldHandle(request, "/cross-site")) | |
| 771 return NOT_HANDLED; | |
| 772 | |
| 773 std::string destAll = net::UnescapeURLComponent( | |
| 774 request.relative_url.substr(std::string("/cross-site").size() + 1), | |
| 775 kUnescapeAll); | |
| 776 | |
| 777 std::string dest = base::StringPrintf( | |
| 778 "//%s:%hu/%s", destAll.substr(0, destAll.find("/")).c_str(), | |
| 779 server->port(), destAll.substr(destAll.find("/") + 1).c_str()); | |
| 780 | |
| 781 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 782 http_response->set_code(HTTP_MOVED_PERMANENTLY); | |
| 783 http_response->AddCustomHeader("Location", dest); | |
| 784 http_response->set_content_type("text/html"); | |
| 785 http_response->set_content(base::StringPrintf( | |
| 786 "<html><head></head><body>Redirecting to %s</body></html>", | |
| 787 dest.c_str())); | |
| 788 return http_response.Pass(); | |
| 789 } | |
| 790 | |
| 791 scoped_ptr<HttpResponse> HandleClientRedirect(const HttpRequest& request) { | |
| 792 if (!ShouldHandle(request, "/client-redirect")) | |
| 793 return NOT_HANDLED; | |
| 794 | |
| 795 GURL request_gurl = ToGURL(request); | |
| 796 std::string dest = | |
| 797 net::UnescapeURLComponent(request_gurl.query(), kUnescapeAll); | |
| 798 | |
| 799 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 800 http_response->set_code(HTTP_OK); | |
| 801 http_response->set_content_type("text/html"); | |
| 802 http_response->set_content(base::StringPrintf( | |
| 803 "<html><head><meta http-equiv=\"refresh\" content=\"0;url=%s\"></head>" | |
| 804 "<body>Redirecting to %s</body></html>", | |
| 805 dest.c_str(), dest.c_str())); | |
| 806 return http_response.Pass(); | |
| 807 } | |
| 808 | |
| 809 scoped_ptr<HttpResponse> HandleDefaultResponse(const HttpRequest& request) { | |
| 810 if (!ShouldHandle(request, "/defaultresponse")) | |
| 811 return NOT_HANDLED; | |
| 812 | |
| 813 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | |
| 814 http_response->set_code(HTTP_OK); | |
| 815 http_response->set_content_type("text/html"); | |
| 816 http_response->set_content("Default response given for path: " + | |
| 817 request.relative_url); | |
| 818 return http_response.Pass(); | |
| 819 } | |
| 820 | |
| 821 class DelayedHttpResponse : public BasicHttpResponse { | |
| 822 public: | |
| 823 DelayedHttpResponse(double delay) : delay_(delay) {} | |
| 824 | |
| 825 void SendResponse(SendBytesCallback send, | |
| 826 SendCompleteCallback done) override { | |
| 827 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 828 FROM_HERE, base::Bind(send, ToResponseString(), done), | |
| 829 base::TimeDelta::FromSecondsD(delay_)); | |
| 830 } | |
| 831 | |
| 832 private: | |
| 833 double delay_; | |
| 834 }; | |
| 835 | |
| 836 scoped_ptr<HttpResponse> HandleSlowServer(const HttpRequest& request) { | |
| 837 if (!ShouldHandle(request, "/slow")) | |
| 838 return NOT_HANDLED; | |
| 839 | |
| 840 double delay = 1.0f; | |
| 841 | |
| 842 GURL request_gurl = ToGURL(request); | |
| 843 if (request_gurl.has_query()) { | |
| 844 delay = std::atof(request_gurl.query().c_str()); | |
| 845 } | |
| 846 | |
| 847 scoped_ptr<BasicHttpResponse> http_response(new DelayedHttpResponse(delay)); | |
| 848 http_response->set_code(HTTP_OK); | |
| 849 http_response->set_content_type("text/plain"); | |
| 850 http_response->set_content(base::StringPrintf("waited %.1f seconds", delay)); | |
| 851 return http_response.Pass(); | |
| 852 } | |
| 853 | |
| 854 void RegisterDefaultHandlers(EmbeddedTestServer* server) { | |
| 855 server->RegisterDefaultHandler(base::Bind(&HandleRedirectConnect)); | |
| 856 server->RegisterDefaultHandler(base::Bind(&HandleServerAuthConnect)); | |
| 857 server->RegisterDefaultHandler(base::Bind(&HandleDefaultConnect)); | |
| 858 | |
| 859 server->RegisterDefaultHandler( | |
| 860 base::Bind(&HandleCacheControl, "/nocachetime/maxage", "max-age=0")); | |
|
mmenke
2015/10/15 19:38:17
Rather than make all of these take a path, suggest
svaldez
2015/10/15 21:04:33
Done.
| |
| 861 server->RegisterDefaultHandler( | |
| 862 base::Bind(&HandleCacheControl, "/nocachetime", "no-cache")); | |
| 863 server->RegisterDefaultHandler( | |
| 864 base::Bind(&HandleCacheControl, "/cachetime", "max-age=60")); | |
| 865 server->RegisterDefaultHandler(base::Bind(&HandleCacheExpires)); | |
| 866 server->RegisterDefaultHandler(base::Bind(&HandleCacheControl, | |
| 867 "/cache/proxy-revalidate", | |
| 868 "max-age=60, proxy-revalidate")); | |
| 869 server->RegisterDefaultHandler( | |
| 870 base::Bind(&HandleCacheControl, "/cache/private", "max-age=3, private")); | |
| 871 server->RegisterDefaultHandler( | |
| 872 base::Bind(&HandleCacheControl, "/cache/public", "max-age=3, public")); | |
| 873 server->RegisterDefaultHandler(base::Bind(&HandleCacheControl, | |
| 874 "/cache/s-maxage", | |
| 875 "public, s-maxage=60, max-age=0")); | |
| 876 server->RegisterDefaultHandler(base::Bind( | |
| 877 &HandleCacheControl, "/cache/must-revalidate", "must-revalidate")); | |
| 878 server->RegisterDefaultHandler(base::Bind(&HandleCacheControl, | |
| 879 "/cache/must-revalidate/max-age", | |
| 880 "max-age=60, must-revalidate")); | |
| 881 server->RegisterDefaultHandler( | |
| 882 base::Bind(&HandleCacheControl, "/cache/no-store", "no-store")); | |
| 883 server->RegisterDefaultHandler(base::Bind( | |
| 884 &HandleCacheControl, "/cache/no-store/max-age", "max-age=60, no-store")); | |
| 885 server->RegisterDefaultHandler( | |
| 886 base::Bind(&HandleCacheControl, "/cache/no-transform", "no-transform")); | |
| 887 | |
| 888 server->RegisterDefaultHandler( | |
| 889 base::Bind(&HandleEchoHeader, "/echoheader", "no-cache")); | |
| 890 server->RegisterDefaultHandler( | |
| 891 base::Bind(&HandleEchoHeader, "/echoheadercache", "max-age=60000")); | |
| 892 server->RegisterDefaultHandler(base::Bind(&HandleEcho)); | |
| 893 server->RegisterDefaultHandler(base::Bind(&HandleEchoTitle)); | |
| 894 server->RegisterDefaultHandler(base::Bind(&HandleEchoAll)); | |
| 895 | |
| 896 server->RegisterDefaultHandler(base::Bind(&HandleSetCookie)); | |
| 897 server->RegisterDefaultHandler(base::Bind(&HandleSetManyCookies)); | |
| 898 server->RegisterDefaultHandler(base::Bind(&HandleExpectAndSetCookie)); | |
| 899 server->RegisterDefaultHandler(base::Bind(&HandleSetHeader)); | |
| 900 server->RegisterDefaultHandler(base::Bind(&HandleNoContent)); | |
| 901 server->RegisterDefaultHandler(base::Bind(&HandleCloseSocket)); | |
| 902 server->RegisterDefaultHandler(base::Bind(&HandleAuthBasic)); | |
| 903 server->RegisterDefaultHandler(base::Bind(&HandleAuthDigest)); | |
| 904 server->RegisterDefaultHandler(base::Bind(&HandleServerRedirect)); | |
| 905 server->RegisterDefaultHandler(base::Bind(&HandleCrossSiteRedirect, server)); | |
| 906 server->RegisterDefaultHandler(base::Bind(&HandleClientRedirect)); | |
| 907 server->RegisterDefaultHandler(base::Bind(&HandleDefaultResponse)); | |
| 908 server->RegisterDefaultHandler(base::Bind(&HandleSlowServer)); | |
| 909 | |
| 910 // TODO(svaldez): HandleDownload | |
| 911 // TODO(svaldez): HandleDownloadFinish | |
| 912 // TODO(svaldez): HandleZipFile | |
| 913 // TODO(svaldez): HandleRangeReset | |
| 914 // TODO(svaldez): HandleSSLManySmallRecords | |
| 915 // TODO(svaldez): HandleChunkedServer | |
| 916 // TODO(svaldez): HandleGetSSLSessionCache | |
| 917 // TODO(svaldez): HandleGetChannelID | |
| 918 // TODO(svaldez): HandleGetClientCert | |
| 919 // TODO(svaldez): HandleClientCipherList | |
| 920 // TODO(svaldez): HandleEchoMultipartPost | |
| 921 } | |
| 922 | |
| 923 } // namespace test_server | |
| 924 } // namespace net | |
| OLD | NEW |