embedded_test_server.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/test/embedded_test_server/embedded_test_server.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/files/file_path.h"
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/file_util.h"
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/path_service.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/run_loop.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stl_util.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/string_util.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/stringprintf.h"
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/threading/thread_restrictions.h"
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/base/ip_endpoint.h"
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/base/net_errors.h"
18b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/test/embedded_test_server/http_connection.h"
19b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/test/embedded_test_server/http_request.h"
20b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "net/test/embedded_test_server/http_response.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/tools/fetch/http_listen_socket.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)namespace net {
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace test_server {
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Handles |request| by serving a file from under |server_root|.
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)scoped_ptr<HttpResponse> HandleFileRequest(
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::FilePath& server_root,
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const HttpRequest& request) {
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // This is a test-only server. Ignore I/O thread restrictions.
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::ThreadRestrictions::ScopedAllowIO allow_io;
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Trim the first byte ('/').
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string request_path(request.relative_url.substr(1));
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Remove the query string if present.
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  size_t query_pos = request_path.find('?');
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (query_pos != std::string::npos)
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    request_path = request_path.substr(0, query_pos);
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::string file_contents;
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!file_util::ReadFileToString(
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          server_root.AppendASCII(request_path), &file_contents)) {
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return scoped_ptr<HttpResponse>(NULL);
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse);
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  http_response->set_code(net::test_server::SUCCESS);
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  http_response->set_content(file_contents);
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return http_response.PassAs<HttpResponse>();
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HttpListenSocket::HttpListenSocket(const SocketDescriptor socket_descriptor,
58b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                   StreamListenSocket::Delegate* delegate)
59b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    : TCPListenSocket(socket_descriptor, delegate) {
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void HttpListenSocket::Listen() {
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
65b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  TCPListenSocket::Listen();
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HttpListenSocket::~HttpListenSocket() {
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)EmbeddedTestServer::EmbeddedTestServer(
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const scoped_refptr<base::SingleThreadTaskRunner>& io_thread)
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : io_thread_(io_thread),
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      port_(-1),
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_factory_(this) {
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(io_thread_);
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
81b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)EmbeddedTestServer::~EmbeddedTestServer() {
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (Started() && !ShutdownAndWaitUntilComplete()) {
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(ERROR) << "EmbeddedTestServer failed to shut down.";
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
89b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool EmbeddedTestServer::InitializeAndWaitUntilReady() {
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::RunLoop run_loop;
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!io_thread_->PostTaskAndReply(
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          FROM_HERE,
95b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          base::Bind(&EmbeddedTestServer::InitializeOnIOThread,
96b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                     base::Unretained(this)),
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          run_loop.QuitClosure())) {
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  run_loop.Run();
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return Started() && base_url_.is_valid();
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
105b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool EmbeddedTestServer::ShutdownAndWaitUntilComplete() {
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(thread_checker_.CalledOnValidThread());
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::RunLoop run_loop;
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!io_thread_->PostTaskAndReply(
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          FROM_HERE,
111b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          base::Bind(&EmbeddedTestServer::ShutdownOnIOThread,
112b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                     base::Unretained(this)),
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          run_loop.QuitClosure())) {
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  run_loop.Run();
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
121b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void EmbeddedTestServer::InitializeOnIOThread() {
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(io_thread_->BelongsToCurrentThread());
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!Started());
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  SocketDescriptor socket_descriptor =
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      TCPListenSocket::CreateAndBindAnyPort("127.0.0.1", &port_);
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (socket_descriptor == TCPListenSocket::kInvalidSocket)
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  listen_socket_ = new HttpListenSocket(socket_descriptor, this);
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  listen_socket_->Listen();
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  IPEndPoint address;
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int result = listen_socket_->GetLocalAddress(&address);
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (result == OK) {
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base_url_ = GURL(std::string("http://") + address.ToString());
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(ERROR) << "GetLocalAddress failed: " << ErrorToString(result);
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
142b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void EmbeddedTestServer::ShutdownOnIOThread() {
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(io_thread_->BelongsToCurrentThread());
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  listen_socket_ = NULL;  // Release the listen socket.
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  STLDeleteContainerPairSecondPointers(connections_.begin(),
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       connections_.end());
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  connections_.clear();
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
151b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void EmbeddedTestServer::HandleRequest(HttpConnection* connection,
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               scoped_ptr<HttpRequest> request) {
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(io_thread_->BelongsToCurrentThread());
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool request_handled = false;
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < request_handlers_.size(); ++i) {
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<HttpResponse> response =
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        request_handlers_[i].Run(*request.get());
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (response.get()) {
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      connection->SendResponse(response.Pass());
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      request_handled = true;
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      break;
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!request_handled) {
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(WARNING) << "Request not handled. Returning 404: "
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 << request->relative_url;
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_ptr<BasicHttpResponse> not_found_response(new BasicHttpResponse);
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    not_found_response->set_code(NOT_FOUND);
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    connection->SendResponse(
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        not_found_response.PassAs<HttpResponse>());
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Drop the connection, since we do not support multiple requests per
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // connection.
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  connections_.erase(connection->socket_.get());
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delete connection;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
182b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)GURL EmbeddedTestServer::GetURL(const std::string& relative_url) const {
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(StartsWithASCII(relative_url, "/", true /* case_sensitive */))
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << relative_url;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base_url_.Resolve(relative_url);
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void EmbeddedTestServer::ServeFilesFromDirectory(
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::FilePath& directory) {
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  RegisterRequestHandler(base::Bind(&HandleFileRequest, directory));
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
193b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void EmbeddedTestServer::RegisterRequestHandler(
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const HandleRequestCallback& callback) {
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_handlers_.push_back(callback);
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
198b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void EmbeddedTestServer::DidAccept(StreamListenSocket* server,
199b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                           StreamListenSocket* connection) {
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(io_thread_->BelongsToCurrentThread());
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HttpConnection* http_connection = new HttpConnection(
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      connection,
204b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::Bind(&EmbeddedTestServer::HandleRequest,
205b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                 weak_factory_.GetWeakPtr()));
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  connections_[connection] = http_connection;
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
209b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void EmbeddedTestServer::DidRead(StreamListenSocket* connection,
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         const char* data,
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                         int length) {
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(io_thread_->BelongsToCurrentThread());
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HttpConnection* http_connection = FindConnection(connection);
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (http_connection == NULL) {
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(WARNING) << "Unknown connection.";
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  http_connection->ReceiveData(std::string(data, length));
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void EmbeddedTestServer::DidClose(StreamListenSocket* connection) {
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(io_thread_->BelongsToCurrentThread());
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HttpConnection* http_connection = FindConnection(connection);
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (http_connection == NULL) {
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(WARNING) << "Unknown connection.";
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delete http_connection;
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  connections_.erase(connection);
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
234b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)HttpConnection* EmbeddedTestServer::FindConnection(
235b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    StreamListenSocket* socket) {
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(io_thread_->BelongsToCurrentThread());
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
238b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  std::map<StreamListenSocket*, HttpConnection*>::iterator it =
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      connections_.find(socket);
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (it == connections_.end()) {
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return it->second;
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace test_server
247b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}  // namespace net
248