Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(146)

Unified Diff: net/test/embedded_test_server/request_helpers.cc

Issue 1376593007: SSL in EmbeddedTestServer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removing unused macros. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/test/embedded_test_server/request_helpers.cc
diff --git a/net/test/embedded_test_server/request_helpers.cc b/net/test/embedded_test_server/request_helpers.cc
new file mode 100644
index 0000000000000000000000000000000000000000..322fc75493295a5ed46fece0f6e66697a32d78a4
--- /dev/null
+++ b/net/test/embedded_test_server/request_helpers.cc
@@ -0,0 +1,239 @@
+// Copyright 2015 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/test/embedded_test_server/request_helpers.h"
+
+#include <stdlib.h>
+#include <ctime>
+#include <map>
+#include <sstream>
+#include <string>
+
+#include "base/base64.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/format_macros.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/threading/thread_restrictions.h"
+#include "net/base/escape.h"
+#include "net/base/url_util.h"
+#include "net/http/http_byte_range.h"
+#include "net/http/http_util.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_request.h"
+#include "net/test/embedded_test_server/http_response.h"
+
+namespace net {
+namespace test_server {
+namespace {
+
+const UnescapeRule::Type kUnescapeAll =
+ UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS |
+ UnescapeRule::SPOOFING_AND_CONTROL_CHARS |
+ UnescapeRule::REPLACE_PLUS_WITH_SPACE;
+
+std::string GetContentType(const base::FilePath& path) {
+ if (path.MatchesExtension(FILE_PATH_LITERAL(".crx")))
+ return "application/x-chrome-extension";
+ else if (path.MatchesExtension(FILE_PATH_LITERAL(".exe")))
mmenke 2015/10/19 18:07:41 Don't need all these else's, since earlier branche
svaldez 2015/10/19 21:56:15 Done.
+ return "application/octet-stream";
+ else if (path.MatchesExtension(FILE_PATH_LITERAL(".gif")))
+ return "image/gif";
+ else if (path.MatchesExtension(FILE_PATH_LITERAL(".jpeg")) ||
+ path.MatchesExtension(FILE_PATH_LITERAL(".jpg")))
+ return "image/jpeg";
mmenke 2015/10/19 18:07:41 nit: Use braces when condition takes more than on
svaldez 2015/10/19 21:56:15 Done.
+ else if (path.MatchesExtension(FILE_PATH_LITERAL(".js")))
+ return "application/javascript";
+ else if (path.MatchesExtension(FILE_PATH_LITERAL(".json")))
+ return "application/json";
+ else if (path.MatchesExtension(FILE_PATH_LITERAL(".pdf")))
+ return "application/pdf";
+ else if (path.MatchesExtension(FILE_PATH_LITERAL(".txt")))
+ return "text/plain";
+ else if (path.MatchesExtension(FILE_PATH_LITERAL(".wav")))
+ return "audio/wav";
+ else if (path.MatchesExtension(FILE_PATH_LITERAL(".xml")))
+ return "text/xml";
+ else if (path.MatchesExtension(FILE_PATH_LITERAL(".html")) ||
+ path.MatchesExtension(FILE_PATH_LITERAL(".htm")))
+ return "text/html";
mmenke 2015/10/19 18:07:41 nit: braces
svaldez 2015/10/19 21:56:15 Done.
+ return "";
+}
+
+}
mmenke 2015/10/19 18:07:41 } // namespace
svaldez 2015/10/19 21:56:15 Done.
+
+void CustomHttpResponse::SendResponse(SendBytesCallback send,
+ SendCompleteCallback done) {
+ std::string response;
+ if (headers_.size() != 0 || contents_.size() != 0)
mmenke 2015/10/19 18:07:41 prefer !headers_.empty() (It may be faster / small
svaldez 2015/10/19 21:56:15 Done.
+ response = headers_ + "\r\n" + contents_;
+ send.Run(response, done);
+}
+
+bool ShouldHandle(const HttpRequest& request, std::string path_prefix) {
mmenke 2015/10/19 18:07:41 std::string -> const std::string&
svaldez 2015/10/19 21:56:15 Done.
+ GURL url = request.ToURL();
+ return url.path() == path_prefix ||
+ base::StartsWith(url.path(), path_prefix + "/",
+ base::CompareCase::SENSITIVE);
+}
+
+scoped_ptr<HttpResponse> HandlePrefixedRequest(
+ std::string prefix,
+ EmbeddedTestServer::HandleRequestCallback handler,
+ const HttpRequest& request) {
+ if (ShouldHandle(request, prefix))
+ return handler.Run(request);
+ return nullptr;
+}
+
+RequestQuery ParseQuery(const GURL& url) {
+ RequestQuery queries;
+ for (QueryIterator it(url); !it.IsAtEnd(); it.Advance()) {
+ queries[net::UnescapeURLComponent(it.GetKey(), kUnescapeAll)].push_back(
+ it.GetUnescapedValue());
+ }
+ return queries;
+}
+
+void GetFilePathWithReplacements(const std::string& original_file_path,
+ const base::StringPairs& text_to_replace,
+ std::string* replacement_path) {
+ std::string new_file_path = original_file_path;
+ bool first_query_parameter = true;
+ for (auto replacement : text_to_replace) {
+ const std::string& old_text = replacement.first;
+ const std::string& new_text = replacement.second;
+ std::string base64_old;
+ std::string base64_new;
+ base::Base64Encode(old_text, &base64_old);
+ base::Base64Encode(new_text, &base64_new);
+ if (first_query_parameter) {
+ new_file_path += "?";
+ first_query_parameter = false;
+ } else {
+ new_file_path += "&";
+ }
+ new_file_path += "replace_text=";
+ new_file_path += base64_old;
+ new_file_path += ":";
+ new_file_path += base64_new;
+ }
+
+ *replacement_path = new_file_path;
+}
+
+// Handles |request| by serving a file from under |server_root|.
+scoped_ptr<HttpResponse> HandleFileRequest(const base::FilePath& server_root,
+ const HttpRequest& request) {
+ // This is a test-only server. Ignore I/O thread restrictions.
mmenke 2015/10/19 18:07:41 Could you add a TODO about figuring out why this i
svaldez 2015/10/19 21:56:15 Done.
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+
+ std::string relative_url(request.relative_url);
+
+ // A proxy request will have an absolute path. Simulate the proxy by stripping
+ // the scheme, host, and port.
+ GURL request_gurl = request.ToURL();
mmenke 2015/10/19 18:07:41 nit: request_url
svaldez 2015/10/19 21:56:15 Done.
+ relative_url = request_gurl.path();
mmenke 2015/10/19 18:07:41 Suggest calling this relative_path (Since this is
svaldez 2015/10/19 21:56:15 Done.
+
+ std::string post_prefix("/post/");
+ if (base::StartsWith(relative_url, post_prefix,
+ base::CompareCase::SENSITIVE)) {
+ relative_url = relative_url.substr(post_prefix.size() - 1);
+ if (request.method != METHOD_POST)
+ return nullptr;
+ }
+
+ RequestQuery query = ParseQuery(request_gurl);
+
+ scoped_ptr<BasicHttpResponse> failed_response(new BasicHttpResponse);
+ failed_response->set_code(HTTP_NOT_FOUND);
+
+ if (query.find("expected_body") != query.end()) {
+ if (request.content.find(query["expected_body"].front()) ==
+ std::string::npos) {
+ return failed_response.Pass();
+ }
+ }
+
+ if (query.find("expected_headers") != query.end()) {
+ for (auto header : query["expected_headers"]) {
+ if (header.find(":") == std::string::npos)
+ return failed_response.Pass();
+ std::string key = header.substr(0, header.find(":"));
+ std::string value = header.substr(header.find(":") + 1);
+ if (request.headers.find(key) == request.headers.end() ||
+ request.headers.at(key) != value) {
+ return failed_response.Pass();
+ }
+ }
+ }
+
+ // Trim the first byte ('/').
+ std::string request_path = relative_url.substr(1);
+ base::FilePath file_path(server_root.AppendASCII(request_path));
+ std::string file_contents;
+ if (!base::ReadFileToString(file_path, &file_contents)) {
+ file_path = file_path.AppendASCII("index.html");
+ if (!base::ReadFileToString(file_path, &file_contents))
+ return nullptr;
+ }
+
+ if (request.method == METHOD_HEAD)
+ file_contents = "";
+
+ if (query.find("replace_text") != query.end()) {
+ for (auto replacement : query["replace_text"]) {
+ std::string find;
+ std::string with;
+ base::Base64Decode(replacement.substr(0, replacement.find(":")), &find);
+ base::Base64Decode(replacement.substr(replacement.find(":") + 1), &with);
+ base::ReplaceSubstringsAfterOffset(&file_contents, 0, find, with);
+ }
+ }
+
+ base::FilePath headers_path(
+ file_path.AddExtension(FILE_PATH_LITERAL("mock-http-headers")));
+
+ if (base::PathExists(headers_path)) {
+ std::string headers_contents;
+
+ if (!base::ReadFileToString(headers_path, &headers_contents))
+ return nullptr;
+
+ scoped_ptr<CustomHttpResponse> http_response(
+ new CustomHttpResponse(headers_contents, file_contents));
+ return http_response.Pass();
+ }
+
+ scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse);
+ http_response->set_code(HTTP_OK);
+
+ if (request.headers.find("Range") != request.headers.end()) {
+ std::vector<HttpByteRange> ranges;
+ HttpUtil::ParseRangeHeader(request.headers.at("Range"), &ranges);
+ if (ranges.size() == 1) {
+ ranges[0].ComputeBounds(file_contents.size());
+ size_t start = ranges[0].first_byte_position();
+ size_t end = ranges[0].last_byte_position();
+
+ http_response->set_code(HTTP_PARTIAL_CONTENT);
+ http_response->AddCustomHeader(
+ "Content-Range",
+ base::StringPrintf("bytes %" PRIuS "-%" PRIuS "/%" PRIuS, start, end,
+ file_contents.size()));
+
+ file_contents = file_contents.substr(start, end - start + 1);
+ }
+ }
+
+ http_response->set_content_type(GetContentType(file_path));
+ http_response->AddCustomHeader("Accept-Ranges", "bytes");
+ http_response->AddCustomHeader("ETag", "'" + file_path.MaybeAsASCII() + "'");
+ http_response->set_content(file_contents);
+ return http_response.Pass();
+}
+
+} // namespace test_server
+} // namespace net

Powered by Google App Engine
This is Rietveld 408576698