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/test/embedded_test_server/embedded_test_server.h" | 5 #include "net/test/embedded_test_server/embedded_test_server.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "net/test/embedded_test_server/http_response.h" | 22 #include "net/test/embedded_test_server/http_response.h" |
23 | 23 |
24 namespace net { | 24 namespace net { |
25 namespace test_server { | 25 namespace test_server { |
26 | 26 |
27 namespace { | 27 namespace { |
28 | 28 |
29 class CustomHttpResponse : public HttpResponse { | 29 class CustomHttpResponse : public HttpResponse { |
30 public: | 30 public: |
31 CustomHttpResponse(const std::string& headers, const std::string& contents) | 31 CustomHttpResponse(const std::string& headers, const std::string& contents) |
32 : headers_(headers), contents_(contents) { | 32 : headers_(headers), contents_(contents) {} |
33 } | |
34 | 33 |
35 virtual std::string ToResponseString() const OVERRIDE { | 34 virtual std::string ToResponseString() const OVERRIDE { |
36 return headers_ + "\r\n" + contents_; | 35 return headers_ + "\r\n" + contents_; |
37 } | 36 } |
38 | 37 |
39 private: | 38 private: |
40 std::string headers_; | 39 std::string headers_; |
41 std::string contents_; | 40 std::string contents_; |
42 | 41 |
43 DISALLOW_COPY_AND_ASSIGN(CustomHttpResponse); | 42 DISALLOW_COPY_AND_ASSIGN(CustomHttpResponse); |
44 }; | 43 }; |
45 | 44 |
46 // Handles |request| by serving a file from under |server_root|. | 45 // Handles |request| by serving a file from under |server_root|. |
47 scoped_ptr<HttpResponse> HandleFileRequest( | 46 scoped_ptr<HttpResponse> HandleFileRequest(const base::FilePath& server_root, |
48 const base::FilePath& server_root, | 47 const HttpRequest& request) { |
49 const HttpRequest& request) { | |
50 // This is a test-only server. Ignore I/O thread restrictions. | 48 // This is a test-only server. Ignore I/O thread restrictions. |
51 base::ThreadRestrictions::ScopedAllowIO allow_io; | 49 base::ThreadRestrictions::ScopedAllowIO allow_io; |
52 | 50 |
53 // Trim the first byte ('/'). | 51 // Trim the first byte ('/'). |
54 std::string request_path(request.relative_url.substr(1)); | 52 std::string request_path(request.relative_url.substr(1)); |
55 | 53 |
56 // Remove the query string if present. | 54 // Remove the query string if present. |
57 size_t query_pos = request_path.find('?'); | 55 size_t query_pos = request_path.find('?'); |
58 if (query_pos != std::string::npos) | 56 if (query_pos != std::string::npos) |
59 request_path = request_path.substr(0, query_pos); | 57 request_path = request_path.substr(0, query_pos); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 } | 94 } |
97 | 95 |
98 HttpListenSocket::~HttpListenSocket() { | 96 HttpListenSocket::~HttpListenSocket() { |
99 DCHECK(thread_checker_.CalledOnValidThread()); | 97 DCHECK(thread_checker_.CalledOnValidThread()); |
100 } | 98 } |
101 | 99 |
102 void HttpListenSocket::DetachFromThread() { | 100 void HttpListenSocket::DetachFromThread() { |
103 thread_checker_.DetachFromThread(); | 101 thread_checker_.DetachFromThread(); |
104 } | 102 } |
105 | 103 |
106 EmbeddedTestServer::EmbeddedTestServer() | 104 EmbeddedTestServer::EmbeddedTestServer() : port_(-1), weak_factory_(this) { |
107 : port_(-1), | |
108 weak_factory_(this) { | |
109 DCHECK(thread_checker_.CalledOnValidThread()); | 105 DCHECK(thread_checker_.CalledOnValidThread()); |
110 } | 106 } |
111 | 107 |
112 EmbeddedTestServer::~EmbeddedTestServer() { | 108 EmbeddedTestServer::~EmbeddedTestServer() { |
113 DCHECK(thread_checker_.CalledOnValidThread()); | 109 DCHECK(thread_checker_.CalledOnValidThread()); |
114 | 110 |
115 if (Started() && !ShutdownAndWaitUntilComplete()) { | 111 if (Started() && !ShutdownAndWaitUntilComplete()) { |
116 LOG(ERROR) << "EmbeddedTestServer failed to shut down."; | 112 LOG(ERROR) << "EmbeddedTestServer failed to shut down."; |
117 } | 113 } |
118 } | 114 } |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 void EmbeddedTestServer::ShutdownOnIOThread() { | 200 void EmbeddedTestServer::ShutdownOnIOThread() { |
205 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); | 201 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); |
206 | 202 |
207 listen_socket_.reset(); | 203 listen_socket_.reset(); |
208 STLDeleteContainerPairSecondPointers(connections_.begin(), | 204 STLDeleteContainerPairSecondPointers(connections_.begin(), |
209 connections_.end()); | 205 connections_.end()); |
210 connections_.clear(); | 206 connections_.clear(); |
211 } | 207 } |
212 | 208 |
213 void EmbeddedTestServer::HandleRequest(HttpConnection* connection, | 209 void EmbeddedTestServer::HandleRequest(HttpConnection* connection, |
214 scoped_ptr<HttpRequest> request) { | 210 scoped_ptr<HttpRequest> request) { |
215 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); | 211 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); |
216 | 212 |
217 bool request_handled = false; | 213 bool request_handled = false; |
218 | 214 |
219 for (size_t i = 0; i < request_handlers_.size(); ++i) { | 215 for (size_t i = 0; i < request_handlers_.size(); ++i) { |
220 scoped_ptr<HttpResponse> response = | 216 scoped_ptr<HttpResponse> response = |
221 request_handlers_[i].Run(*request.get()); | 217 request_handlers_[i].Run(*request.get()); |
222 if (response.get()) { | 218 if (response.get()) { |
223 connection->SendResponse(response.Pass()); | 219 connection->SendResponse(response.Pass()); |
224 request_handled = true; | 220 request_handled = true; |
225 break; | 221 break; |
226 } | 222 } |
227 } | 223 } |
228 | 224 |
229 if (!request_handled) { | 225 if (!request_handled) { |
230 LOG(WARNING) << "Request not handled. Returning 404: " | 226 LOG(WARNING) << "Request not handled. Returning 404: " |
231 << request->relative_url; | 227 << request->relative_url; |
232 scoped_ptr<BasicHttpResponse> not_found_response(new BasicHttpResponse); | 228 scoped_ptr<BasicHttpResponse> not_found_response(new BasicHttpResponse); |
233 not_found_response->set_code(HTTP_NOT_FOUND); | 229 not_found_response->set_code(HTTP_NOT_FOUND); |
234 connection->SendResponse( | 230 connection->SendResponse(not_found_response.PassAs<HttpResponse>()); |
235 not_found_response.PassAs<HttpResponse>()); | |
236 } | 231 } |
237 | 232 |
238 // Drop the connection, since we do not support multiple requests per | 233 // Drop the connection, since we do not support multiple requests per |
239 // connection. | 234 // connection. |
240 connections_.erase(connection->socket_.get()); | 235 connections_.erase(connection->socket_.get()); |
241 delete connection; | 236 delete connection; |
242 } | 237 } |
243 | 238 |
244 GURL EmbeddedTestServer::GetURL(const std::string& relative_url) const { | 239 GURL EmbeddedTestServer::GetURL(const std::string& relative_url) const { |
245 DCHECK(Started()) << "You must start the server first."; | 240 DCHECK(Started()) << "You must start the server first."; |
246 DCHECK(StartsWithASCII(relative_url, "/", true /* case_sensitive */)) | 241 DCHECK(StartsWithASCII(relative_url, "/", true /* case_sensitive */)) |
247 << relative_url; | 242 << relative_url; |
248 return base_url_.Resolve(relative_url); | 243 return base_url_.Resolve(relative_url); |
249 } | 244 } |
250 | 245 |
251 void EmbeddedTestServer::ServeFilesFromDirectory( | 246 void EmbeddedTestServer::ServeFilesFromDirectory( |
252 const base::FilePath& directory) { | 247 const base::FilePath& directory) { |
253 RegisterRequestHandler(base::Bind(&HandleFileRequest, directory)); | 248 RegisterRequestHandler(base::Bind(&HandleFileRequest, directory)); |
254 } | 249 } |
255 | 250 |
256 void EmbeddedTestServer::RegisterRequestHandler( | 251 void EmbeddedTestServer::RegisterRequestHandler( |
257 const HandleRequestCallback& callback) { | 252 const HandleRequestCallback& callback) { |
258 request_handlers_.push_back(callback); | 253 request_handlers_.push_back(callback); |
259 } | 254 } |
260 | 255 |
261 void EmbeddedTestServer::DidAccept( | 256 void EmbeddedTestServer::DidAccept(StreamListenSocket* server, |
262 StreamListenSocket* server, | 257 scoped_ptr<StreamListenSocket> connection) { |
263 scoped_ptr<StreamListenSocket> connection) { | |
264 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); | 258 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); |
265 | 259 |
266 HttpConnection* http_connection = new HttpConnection( | 260 HttpConnection* http_connection = |
267 connection.Pass(), | 261 new HttpConnection(connection.Pass(), |
268 base::Bind(&EmbeddedTestServer::HandleRequest, | 262 base::Bind(&EmbeddedTestServer::HandleRequest, |
269 weak_factory_.GetWeakPtr())); | 263 weak_factory_.GetWeakPtr())); |
270 // TODO(szym): Make HttpConnection the StreamListenSocket delegate. | 264 // TODO(szym): Make HttpConnection the StreamListenSocket delegate. |
271 connections_[http_connection->socket_.get()] = http_connection; | 265 connections_[http_connection->socket_.get()] = http_connection; |
272 } | 266 } |
273 | 267 |
274 void EmbeddedTestServer::DidRead(StreamListenSocket* connection, | 268 void EmbeddedTestServer::DidRead(StreamListenSocket* connection, |
275 const char* data, | 269 const char* data, |
276 int length) { | 270 int length) { |
277 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); | 271 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); |
278 | 272 |
279 HttpConnection* http_connection = FindConnection(connection); | 273 HttpConnection* http_connection = FindConnection(connection); |
280 if (http_connection == NULL) { | 274 if (http_connection == NULL) { |
281 LOG(WARNING) << "Unknown connection."; | 275 LOG(WARNING) << "Unknown connection."; |
282 return; | 276 return; |
283 } | 277 } |
284 http_connection->ReceiveData(std::string(data, length)); | 278 http_connection->ReceiveData(std::string(data, length)); |
285 } | 279 } |
286 | 280 |
287 void EmbeddedTestServer::DidClose(StreamListenSocket* connection) { | 281 void EmbeddedTestServer::DidClose(StreamListenSocket* connection) { |
288 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); | 282 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); |
289 | 283 |
290 HttpConnection* http_connection = FindConnection(connection); | 284 HttpConnection* http_connection = FindConnection(connection); |
291 if (http_connection == NULL) { | 285 if (http_connection == NULL) { |
292 LOG(WARNING) << "Unknown connection."; | 286 LOG(WARNING) << "Unknown connection."; |
293 return; | 287 return; |
294 } | 288 } |
295 delete http_connection; | 289 delete http_connection; |
296 connections_.erase(connection); | 290 connections_.erase(connection); |
297 } | 291 } |
298 | 292 |
299 HttpConnection* EmbeddedTestServer::FindConnection( | 293 HttpConnection* EmbeddedTestServer::FindConnection(StreamListenSocket* socket) { |
300 StreamListenSocket* socket) { | |
301 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); | 294 DCHECK(io_thread_->message_loop_proxy()->BelongsToCurrentThread()); |
302 | 295 |
303 std::map<StreamListenSocket*, HttpConnection*>::iterator it = | 296 std::map<StreamListenSocket*, HttpConnection*>::iterator it = |
304 connections_.find(socket); | 297 connections_.find(socket); |
305 if (it == connections_.end()) { | 298 if (it == connections_.end()) { |
306 return NULL; | 299 return NULL; |
307 } | 300 } |
308 return it->second; | 301 return it->second; |
309 } | 302 } |
310 | 303 |
(...skipping 16 matching lines...) Expand all Loading... |
327 FROM_HERE, closure, run_loop.QuitClosure())) { | 320 FROM_HERE, closure, run_loop.QuitClosure())) { |
328 return false; | 321 return false; |
329 } | 322 } |
330 run_loop.Run(); | 323 run_loop.Run(); |
331 | 324 |
332 return true; | 325 return true; |
333 } | 326 } |
334 | 327 |
335 } // namespace test_server | 328 } // namespace test_server |
336 } // namespace net | 329 } // namespace net |
OLD | NEW |