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