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

Side by Side Diff: net/test/embedded_test_server/request_handler_util.cc

Issue 1376593007: SSL in EmbeddedTestServer (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Typo fix. Created 5 years, 1 month 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 unified diff | Download patch
OLDNEW
(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_handler_util.h"
6
7 #include <stdlib.h>
8 #include <ctime>
9 #include <sstream>
10
11 #include "base/base64.h"
12 #include "base/files/file_util.h"
13 #include "base/format_macros.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/threading/thread_restrictions.h"
17 #include "net/base/escape.h"
18 #include "net/base/url_util.h"
19 #include "net/http/http_byte_range.h"
20 #include "net/http/http_util.h"
21 #include "net/test/embedded_test_server/http_request.h"
22 #include "url/gurl.h"
23
24 namespace net {
25 namespace test_server {
26 namespace {
27
28 const UnescapeRule::Type kUnescapeAll =
29 UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS |
30 UnescapeRule::SPOOFING_AND_CONTROL_CHARS |
31 UnescapeRule::REPLACE_PLUS_WITH_SPACE;
32
33 std::string GetContentType(const base::FilePath& path) {
34 if (path.MatchesExtension(FILE_PATH_LITERAL(".crx")))
35 return "application/x-chrome-extension";
36 if (path.MatchesExtension(FILE_PATH_LITERAL(".exe")))
37 return "application/octet-stream";
38 if (path.MatchesExtension(FILE_PATH_LITERAL(".gif")))
39 return "image/gif";
40 if (path.MatchesExtension(FILE_PATH_LITERAL(".jpeg")) ||
41 path.MatchesExtension(FILE_PATH_LITERAL(".jpg"))) {
42 return "image/jpeg";
43 }
44 if (path.MatchesExtension(FILE_PATH_LITERAL(".js")))
45 return "application/javascript";
46 if (path.MatchesExtension(FILE_PATH_LITERAL(".json")))
47 return "application/json";
48 if (path.MatchesExtension(FILE_PATH_LITERAL(".pdf")))
49 return "application/pdf";
50 if (path.MatchesExtension(FILE_PATH_LITERAL(".txt")))
51 return "text/plain";
52 if (path.MatchesExtension(FILE_PATH_LITERAL(".wav")))
53 return "audio/wav";
54 if (path.MatchesExtension(FILE_PATH_LITERAL(".xml")))
55 return "text/xml";
56 if (path.MatchesExtension(FILE_PATH_LITERAL(".html")) ||
57 path.MatchesExtension(FILE_PATH_LITERAL(".htm"))) {
58 return "text/html";
59 }
60 return "";
61 }
62
63 } // namespace
64
65 bool ShouldHandle(const HttpRequest& request, const std::string& path_prefix) {
66 GURL url = request.GetURL();
67 return url.path() == path_prefix ||
68 base::StartsWith(url.path(), path_prefix + "/",
69 base::CompareCase::SENSITIVE);
70 }
71
72 scoped_ptr<HttpResponse> HandlePrefixedRequest(
73 const std::string& prefix,
74 const EmbeddedTestServer::HandleRequestCallback& handler,
75 const HttpRequest& request) {
76 if (ShouldHandle(request, prefix))
77 return handler.Run(request);
78 return nullptr;
79 }
80
81 RequestQuery ParseQuery(const GURL& url) {
82 RequestQuery queries;
83 for (QueryIterator it(url); !it.IsAtEnd(); it.Advance()) {
84 queries[net::UnescapeURLComponent(it.GetKey(), kUnescapeAll)].push_back(
85 it.GetUnescapedValue());
86 }
87 return queries;
88 }
89
90 void GetFilePathWithReplacements(const std::string& original_file_path,
91 const base::StringPairs& text_to_replace,
92 std::string* replacement_path) {
93 std::string new_file_path = original_file_path;
94 for (const auto& replacement : text_to_replace) {
95 const std::string& old_text = replacement.first;
96 const std::string& new_text = replacement.second;
97 std::string base64_old;
98 std::string base64_new;
99 base::Base64Encode(old_text, &base64_old);
100 base::Base64Encode(new_text, &base64_new);
101 if (new_file_path == original_file_path)
102 new_file_path += "?";
103 else
104 new_file_path += "&";
105 new_file_path += "replace_text=";
106 new_file_path += base64_old;
107 new_file_path += ":";
108 new_file_path += base64_new;
109 }
110
111 *replacement_path = new_file_path;
112 }
113
114 // Handles |request| by serving a file from under |server_root|.
115 scoped_ptr<HttpResponse> HandleFileRequest(const base::FilePath& server_root,
116 const HttpRequest& request) {
117 // This is a test-only server. Ignore I/O thread restrictions.
118 // TODO(svaldez): Figure out why thread is I/O restricted in the first place.
119 base::ThreadRestrictions::ScopedAllowIO allow_io;
120
121 // A proxy request will have an absolute path. Simulate the proxy by stripping
122 // the scheme, host, and port.
123 GURL request_url = request.GetURL();
124 std::string relative_path(request_url.path());
125
126 std::string post_prefix("/post/");
127 if (base::StartsWith(relative_path, post_prefix,
128 base::CompareCase::SENSITIVE)) {
129 if (request.method != METHOD_POST)
130 return nullptr;
131 relative_path = relative_path.substr(post_prefix.size() - 1);
132 }
133
134 RequestQuery query = ParseQuery(request_url);
135
136 scoped_ptr<BasicHttpResponse> failed_response(new BasicHttpResponse);
137 failed_response->set_code(HTTP_NOT_FOUND);
138
139 if (query.find("expected_body") != query.end()) {
140 if (request.content.find(query["expected_body"].front()) ==
141 std::string::npos) {
142 return failed_response.Pass();
143 }
144 }
145
146 if (query.find("expected_headers") != query.end()) {
147 for (const auto& header : query["expected_headers"]) {
148 if (header.find(":") == std::string::npos)
149 return failed_response.Pass();
150 std::string key = header.substr(0, header.find(":"));
151 std::string value = header.substr(header.find(":") + 1);
152 if (request.headers.find(key) == request.headers.end() ||
153 request.headers.at(key) != value) {
154 return failed_response.Pass();
155 }
156 }
157 }
158
159 // Trim the first byte ('/').
160 DCHECK(base::StartsWith(relative_path, "/", base::CompareCase::SENSITIVE));
161 std::string request_path = relative_path.substr(1);
162 base::FilePath file_path(server_root.AppendASCII(request_path));
163 std::string file_contents;
164 if (!base::ReadFileToString(file_path, &file_contents)) {
165 file_path = file_path.AppendASCII("index.html");
166 if (!base::ReadFileToString(file_path, &file_contents))
167 return nullptr;
168 }
169
170 if (request.method == METHOD_HEAD)
171 file_contents = "";
172
173 if (query.find("replace_text") != query.end()) {
174 for (const auto& replacement : query["replace_text"]) {
175 if (replacement.find(":") == std::string::npos)
176 return failed_response.Pass();
177 std::string find;
178 std::string with;
179 base::Base64Decode(replacement.substr(0, replacement.find(":")), &find);
180 base::Base64Decode(replacement.substr(replacement.find(":") + 1), &with);
181 base::ReplaceSubstringsAfterOffset(&file_contents, 0, find, with);
182 }
183 }
184
185 base::FilePath headers_path(
186 file_path.AddExtension(FILE_PATH_LITERAL("mock-http-headers")));
187
188 if (base::PathExists(headers_path)) {
189 std::string headers_contents;
190
191 if (!base::ReadFileToString(headers_path, &headers_contents))
192 return nullptr;
193
194 return make_scoped_ptr(
195 new RawHttpResponse(headers_contents, file_contents));
196 }
197
198 scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse);
199 http_response->set_code(HTTP_OK);
200
201 if (request.headers.find("Range") != request.headers.end()) {
202 std::vector<HttpByteRange> ranges;
203
204 if (HttpUtil::ParseRangeHeader(request.headers.at("Range"), &ranges) &&
205 ranges.size() == 1) {
206 ranges[0].ComputeBounds(file_contents.size());
207 size_t start = ranges[0].first_byte_position();
208 size_t end = ranges[0].last_byte_position();
209
210 http_response->set_code(HTTP_PARTIAL_CONTENT);
211 http_response->AddCustomHeader(
212 "Content-Range",
213 base::StringPrintf("bytes %" PRIuS "-%" PRIuS "/%" PRIuS, start, end,
214 file_contents.size()));
215
216 file_contents = file_contents.substr(start, end - start + 1);
217 }
218 }
219
220 http_response->set_content_type(GetContentType(file_path));
221 http_response->AddCustomHeader("Accept-Ranges", "bytes");
222 http_response->AddCustomHeader("ETag", "'" + file_path.MaybeAsASCII() + "'");
223 http_response->set_content(file_contents);
224 return http_response.Pass();
225 }
226
227 } // namespace test_server
228 } // namespace net
OLDNEW
« no previous file with comments | « net/test/embedded_test_server/request_handler_util.h ('k') | remoting/protocol/ssl_hmac_channel_authenticator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698