embedded_test_server.h revision 58537e28ecd584eab876aee8be7156509866d23a
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 3// found in the LICENSE file. 4 5#ifndef NET_TEST_EMBEDDED_TEST_SERVER_EMBEDDED_TEST_SERVER_H_ 6#define NET_TEST_EMBEDDED_TEST_SERVER_EMBEDDED_TEST_SERVER_H_ 7 8#include <map> 9#include <string> 10#include <vector> 11 12#include "base/basictypes.h" 13#include "base/callback.h" 14#include "base/compiler_specific.h" 15#include "base/memory/ref_counted.h" 16#include "base/memory/weak_ptr.h" 17#include "base/threading/thread_checker.h" 18#include "net/socket/tcp_listen_socket.h" 19#include "url/gurl.h" 20 21namespace base { 22class FilePath; 23} 24 25namespace net { 26namespace test_server { 27 28class HttpConnection; 29class HttpResponse; 30struct HttpRequest; 31 32// This class is required to be able to have composition instead of inheritance, 33class HttpListenSocket : public TCPListenSocket { 34 public: 35 HttpListenSocket(const SocketDescriptor socket_descriptor, 36 StreamListenSocket::Delegate* delegate); 37 virtual ~HttpListenSocket(); 38 virtual void Listen(); 39 40 private: 41 42 base::ThreadChecker thread_checker_; 43}; 44 45// Class providing an HTTP server for testing purpose. This is a basic server 46// providing only an essential subset of HTTP/1.1 protocol. Especially, 47// it assumes that the request syntax is correct. It *does not* support 48// a Chunked Transfer Encoding. 49// 50// The common use case is below: 51// 52// base::Thread io_thread_; 53// scoped_ptr<EmbeddedTestServer> test_server_; 54// 55// void SetUp() { 56// base::Thread::Options thread_options; 57// thread_options.message_loop_type = base::MessageLoop::TYPE_IO; 58// ASSERT_TRUE(io_thread_.StartWithOptions(thread_options)); 59// 60// test_server_.reset( 61// new EmbeddedTestServer(io_thread_.message_loop_proxy())); 62// ASSERT_TRUE(test_server_.InitializeAndWaitUntilReady()); 63// test_server_->RegisterRequestHandler( 64// base::Bind(&FooTest::HandleRequest, base::Unretained(this))); 65// } 66// 67// scoped_ptr<HttpResponse> HandleRequest(const HttpRequest& request) { 68// GURL absolute_url = test_server_->GetURL(request.relative_url); 69// if (absolute_url.path() != "/test") 70// return scoped_ptr<HttpResponse>(); 71// 72// scoped_ptr<HttpResponse> http_response(new HttpResponse()); 73// http_response->set_code(test_server::SUCCESS); 74// http_response->set_content("hello"); 75// http_response->set_content_type("text/plain"); 76// return http_response.Pass(); 77// } 78// 79class EmbeddedTestServer : public StreamListenSocket::Delegate { 80 public: 81 typedef base::Callback<scoped_ptr<HttpResponse>( 82 const HttpRequest& request)> HandleRequestCallback; 83 84 // Creates a http test server. |io_thread| is a task runner 85 // with IO message loop, used as a backend thread. 86 // InitializeAndWaitUntilReady() must be called to start the server. 87 explicit EmbeddedTestServer( 88 const scoped_refptr<base::SingleThreadTaskRunner>& io_thread); 89 virtual ~EmbeddedTestServer(); 90 91 // Initializes and waits until the server is ready to accept requests. 92 bool InitializeAndWaitUntilReady() WARN_UNUSED_RESULT; 93 94 // Shuts down the http server and waits until the shutdown is complete. 95 bool ShutdownAndWaitUntilComplete() WARN_UNUSED_RESULT; 96 97 // Checks if the server is started. 98 bool Started() const { 99 return listen_socket_.get() != NULL; 100 } 101 102 // Returns the base URL to the server, which looks like 103 // http://127.0.0.1:<port>/, where <port> is the actual port number used by 104 // the server. 105 const GURL& base_url() const { return base_url_; } 106 107 // Returns a URL to the server based on the given relative URL, which 108 // should start with '/'. For example: GetURL("/path?query=foo") => 109 // http://127.0.0.1:<port>/path?query=foo. 110 GURL GetURL(const std::string& relative_url) const; 111 112 // Returns the port number used by the server. 113 int port() const { return port_; } 114 115 // Registers request handler which serves files from |directory|. 116 // For instance, a request to "/foo.html" is served by "foo.html" under 117 // |directory|. Files under sub directories are also handled in the same way 118 // (i.e. "/foo/bar.html" is served by "foo/bar.html" under |directory|). 119 void ServeFilesFromDirectory(const base::FilePath& directory); 120 121 // The most general purpose method. Any request processing can be added using 122 // this method. Takes ownership of the object. The |callback| is called 123 // on UI thread. 124 void RegisterRequestHandler(const HandleRequestCallback& callback); 125 126 private: 127 // Initializes and starts the server. If initialization succeeds, Starts() 128 // will return true. 129 void InitializeOnIOThread(); 130 131 // Shuts down the server. 132 void ShutdownOnIOThread(); 133 134 // Handles a request when it is parsed. It passes the request to registed 135 // request handlers and sends a http response. 136 void HandleRequest(HttpConnection* connection, 137 scoped_ptr<HttpRequest> request); 138 139 // StreamListenSocket::Delegate overrides: 140 virtual void DidAccept(StreamListenSocket* server, 141 scoped_ptr<StreamListenSocket> connection) OVERRIDE; 142 virtual void DidRead(StreamListenSocket* connection, 143 const char* data, 144 int length) OVERRIDE; 145 virtual void DidClose(StreamListenSocket* connection) OVERRIDE; 146 147 HttpConnection* FindConnection(StreamListenSocket* socket); 148 149 // Posts a task to the |io_thread_| and waits for a reply. 150 bool PostTaskToIOThreadAndWait( 151 const base::Closure& closure) WARN_UNUSED_RESULT; 152 153 scoped_refptr<base::SingleThreadTaskRunner> io_thread_; 154 155 scoped_ptr<HttpListenSocket> listen_socket_; 156 int port_; 157 GURL base_url_; 158 159 // Owns the HttpConnection objects. 160 std::map<StreamListenSocket*, HttpConnection*> connections_; 161 162 // Vector of registered request handlers. 163 std::vector<HandleRequestCallback> request_handlers_; 164 165 // Note: This should remain the last member so it'll be destroyed and 166 // invalidate its weak pointers before any other members are destroyed. 167 base::WeakPtrFactory<EmbeddedTestServer> weak_factory_; 168 169 base::ThreadChecker thread_checker_; 170 171 DISALLOW_COPY_AND_ASSIGN(EmbeddedTestServer); 172}; 173 174} // namespace test_servers 175} // namespace net 176 177#endif // NET_TEST_EMBEDDED_TEST_SERVER_EMBEDDED_TEST_SERVER_H_ 178