| 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 |