Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(283)

Side by Side Diff: chrome/browser/chromeos/drive/test_servers/http_server.cc

Issue 11088073: HTTP server for testing Google Drive. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Fixed response generation. Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 #include "chrome/browser/chromeos/drive/test_servers/http_server.h"
6
7 #include "base/bind.h"
8 #include "base/stl_util.h"
9 #include "base/file_util.h"
10 #include "base/stringprintf.h"
11 #include "chrome/browser/chromeos/drive/test_servers/http_request.h"
12 #include "chrome/browser/chromeos/drive/test_servers/http_response.h"
13 #include "chrome/browser/google_apis/gdata_test_util.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "net/tools/fetch/http_listen_socket.h"
16
17 #include <sstream>
18
19 namespace drive {
20 namespace test_servers {
21
22 using content::BrowserThread;
23
24 namespace {
25
26 const int kPort = 8040;
27 const char kIp[] = "127.0.0.1";
28 const int kRetries = 10;
29
30 // Callback about success or failure in creating a server. |result| is a pointer
31 // to result passed back to HttpServer::CreateForTesting. |server| is a
32 // pointer to the created server or NULL in case of failure.
33 static void OnCreatedForTesting(HttpServer** result,
34 HttpServer* server) {
35 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
36 *result = server;
37 MessageLoop::current()->Quit();
38 }
39
40 // Callback to handle requests with default predefined response for requests
41 // matching the address |url|.
42 scoped_ptr<HttpResponse> HandleDefaultRequest(const GURL& url,
43 const HttpResponse& response,
44 const HttpRequest* request) {
45 if (url.path() != request->uri.path())
46 return scoped_ptr<HttpResponse>(NULL);
47 return scoped_ptr<HttpResponse>(new HttpResponse(response));
48 }
49
50 } // namespace
51
52 HttpListenSocket::HttpListenSocket(const SocketDescriptor socket_descriptor,
53 net::StreamListenSocket::Delegate* delegate)
54 : net::TCPListenSocket(socket_descriptor, delegate) {
55 }
56
57 void HttpListenSocket::Listen() {
58 net::TCPListenSocket::Listen();
59 }
60
61 HttpListenSocket::~HttpListenSocket() {
62 }
63
64 // static
65 scoped_ptr<HttpServer> HttpServer::CreateForTesting() {
66 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
67
68 HttpServer* result = NULL;
69 BrowserThread::PostTask(
satorux1 2012/11/13 05:28:34 You want to call OnCreatedForTesting on UI thread,
mtomasz 2012/11/13 12:23:07 Hm. I am concerned that passing a result may be qu
satorux1 2012/11/14 01:42:23 What about doing something like this: HttpServer*
mtomasz 2012/11/14 03:23:35 This is a good idea. Done sth like this.
70 BrowserThread::IO,
71 FROM_HERE,
72 base::Bind(
73 &HttpServer::CreateOnIOThread,
74 base::Bind(&OnCreatedForTesting, &result)));
75
76 // Wait for the task completion.
77 MessageLoop::current()->Run();
78 return scoped_ptr<HttpServer>(result);
79 }
80
81 // static
82 void HttpServer::CreateOnIOThread(const CreateCallback& callback) {
83 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
84
85 int retries_left = kRetries + 1;
86 int try_port = kPort;
87 HttpServer* server = NULL;
88
89 while (retries_left > 0) {
90 SocketDescriptor socket_descriptor = net::TCPListenSocket::CreateAndBind(
91 kIp,
92 try_port);
93 if (socket_descriptor != net::TCPListenSocket::kInvalidSocket) {
94 server = new HttpServer(try_port, socket_descriptor);
95 break;
96 }
97 retries_left--;
satorux1 2012/11/13 05:28:34 nit: --retries_left; post-increment/decrement is
mtomasz 2012/11/13 12:23:07 Done.
98 try_port++;
99 }
100
101 BrowserThread::PostTask(BrowserThread::UI,
102 FROM_HERE,
103 base::Bind(callback, server));
104 }
105
106 HttpServer::HttpServer(int port,
107 const SocketDescriptor& socket_descriptor)
108 : listen_socket_(new HttpListenSocket(
109 socket_descriptor,
110 ALLOW_THIS_IN_INITIALIZER_LIST(this))),
111 port_(port),
112 last_unique_id_(0),
113 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
114 listen_socket_->Listen();
115 base_url_ = GURL(base::StringPrintf("http://%s:%d", kIp, port_));
116 }
117
118 HttpServer::~HttpServer() {
119 STLDeleteContainerPairSecondPointers(connections_.begin(),
120 connections_.end());
121 }
122
123 void HttpServer::HandleRequest(HttpConnection* connection,
124 scoped_ptr<HttpRequest> request) {
125 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
126
127 for (size_t i = 0; i < request_handlers_.size(); ++i) {
128 scoped_ptr<HttpResponse> response =
129 request_handlers_[i].Run(request.get());
130 if (response.get()) {
131 connection->SendResponse(response.Pass());
132 return;
133 }
134 }
135
136 LOG(WARNING) << "Request not handled. Returning 404.";
137 scoped_ptr<HttpResponse> not_found_response(new HttpResponse());
138 not_found_response->code = NOT_FOUND;
139 connection->SendResponse(not_found_response.Pass());
140 }
141
142 GURL HttpServer::GetBaseURL() {
143 return base_url_;
144 }
145
146 void HttpServer::RegisterRequestHandler(
147 const HandleRequestCallback& callback) {
148 request_handlers_.push_back(callback);
149 }
150
151 GURL HttpServer::RegisterDefaultResponse(
152 const std::string& relative_path,
153 const HttpResponse& default_response) {
154 GURL request_url = base_url_.Resolve(relative_path);
155 const HandleRequestCallback callback =
156 base::Bind(&HandleDefaultRequest,
157 request_url,
158 default_response);
159 request_handlers_.push_back(callback);
160
161 return request_url;
162 }
163
164 GURL HttpServer::RegisterTextResponse(
165 const std::string& relative_path,
166 const std::string& content,
167 const std::string& content_type,
168 const ResponseCode response_code) {
169 HttpResponse default_response;
170 default_response.content = content;
171 default_response.content_type = content_type;
172 default_response.code = response_code;
173
174 return RegisterDefaultResponse(relative_path, default_response);
175 }
176
177 GURL HttpServer::RegisterSimpleTextResponse(
178 const std::string& content,
179 const std::string& content_type) {
180 return RegisterTextResponse(GenerateUniqueIdentifier(),
181 content,
182 content_type,
183 SUCCESS);
184 }
185
186 GURL HttpServer::RegisterFileResponse(
187 const std::string& relative_path,
188 const FilePath& file_path,
189 const std::string& content_type,
190 const ResponseCode response_code) {
191 HttpResponse default_response;
192
193 DCHECK(file_util::ReadFileToString(file_path, &default_response.content)) <<
194 "Failed to open the file: " << file_path.value();
195
196 default_response.content_type = content_type;
197 default_response.code = response_code;
198
199 return RegisterDefaultResponse(relative_path, default_response);
200 }
201
202 GURL HttpServer::RegisterSimpleFileResponse(
203 const FilePath& file_path,
204 const std::string& content_type) {
205 return RegisterFileResponse(
206 GenerateUniqueIdentifier() + "/" + file_path.BaseName().value(),
207 file_path,
208 content_type,
209 SUCCESS);
210 }
211
212 std::string HttpServer::GenerateUniqueIdentifier() {
213 std::stringstream result_builder;
214 result_builder << ++last_unique_id_;
215 return result_builder.str();
216 }
217
218 void HttpServer::DidAccept(net::StreamListenSocket* server,
219 net::StreamListenSocket* connection) {
220 HttpConnection* http_connection = new HttpConnection(
221 connection,
222 base::Bind(&HttpServer::HandleRequest, weak_factory_.GetWeakPtr()));
223 connections_[connection] = http_connection;
224 }
225
226 void HttpServer::DidRead(net::StreamListenSocket* connection,
227 const char* data,
228 int length) {
229 HttpConnection* http_connection = FindConnection(connection);
230 if (http_connection == NULL) {
231 LOG(WARNING) << "Unknown connection.";
232 return;
233 }
234 http_connection->ReceiveData(std::string(data, length));
235 }
236
237 void HttpServer::DidClose(net::StreamListenSocket* connection) {
238 HttpConnection* http_connection = FindConnection(connection);
239 if (http_connection == NULL) {
240 LOG(WARNING) << "Unknown connection.";
241 return;
242 }
243 delete http_connection;
244 connections_.erase(connection);
245 }
246
247 HttpConnection* HttpServer::FindConnection(
248 net::StreamListenSocket* socket) {
249 std::map<net::StreamListenSocket*, HttpConnection*>::iterator it =
250 connections_.find(socket);
251 if (it == connections_.end()) {
252 return NULL;
253 }
254 return it->second;
255 }
256
257 } // namespace test_servers
258 } // namespace drive
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698