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

Side by Side Diff: chrome/browser/google_apis/test_server/http_server.cc

Issue 11088073: HTTP server for testing Google Drive. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Addressed most comments. 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/google_apis/test_server/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/google_apis/test_server/http_request.h"
12 #include "chrome/browser/google_apis/test_server/http_response.h"
13 #include "chrome/browser/google_apis/gdata_test_util.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "content/public/test/test_utils.h"
16 #include "net/tools/fetch/http_listen_socket.h"
17
18 namespace drive {
19 namespace test_server {
20
21 using content::BrowserThread;
22
23 namespace {
24
25 const int kPort = 8040;
26 const char kIp[] = "127.0.0.1";
27 const int kRetries = 10;
28
29 // Callback to handle requests with default predefined response for requests
30 // matching the address |url|.
31 scoped_ptr<HttpResponse> HandleDefaultRequest(const GURL& url,
32 const HttpResponse& response,
33 const HttpRequest& request) {
34 if (url.path() != request.uri.path())
35 return scoped_ptr<HttpResponse>(NULL);
36 return scoped_ptr<HttpResponse>(new HttpResponse(response));
37 }
38
39 } // namespace
40
41 HttpListenSocket::HttpListenSocket(const SocketDescriptor socket_descriptor,
42 net::StreamListenSocket::Delegate* delegate)
43 : net::TCPListenSocket(socket_descriptor, delegate) {
44 }
45
46 void HttpListenSocket::Listen() {
47 net::TCPListenSocket::Listen();
48 }
49
50 HttpListenSocket::~HttpListenSocket() {
51 }
52
53 bool HttpServer::InitializeAndWaitUntilReady() {
54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
55
56 BrowserThread::PostTask(
57 BrowserThread::IO,
58 FROM_HERE,
59 base::Bind(&HttpServer::InitializeOnIOThread,
60 base::Unretained(this),
61 InitializeCallback()));
62
63 // Wait for the task completion.
64 content::RunAllPendingInMessageLoop(BrowserThread::IO);
65 content::RunAllPendingInMessageLoop();
66
67 return Started();
68 }
69
70 void HttpServer::InitializeOnIOThread(const InitializeCallback& callback) {
71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
72 DCHECK(!Started());
73
74 int retries_left = kRetries + 1;
75 int try_port = kPort;
76
77 while (retries_left > 0) {
78 SocketDescriptor socket_descriptor = net::TCPListenSocket::CreateAndBind(
79 kIp,
80 try_port);
81 if (socket_descriptor != net::TCPListenSocket::kInvalidSocket) {
82 listen_socket_ = new HttpListenSocket(socket_descriptor, this);
83 listen_socket_->Listen();
84 base_url_ = GURL(base::StringPrintf("http://%s:%d", kIp, try_port));
85 port_ = try_port;
86 break;
87 }
88 retries_left--;
89 try_port++;
90 }
91
92 if (!callback.is_null())
93 callback.Run(listen_socket_.get() != NULL);
94 }
95
96 HttpServer::HttpServer()
97 : port_(-1),
98 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
99 }
100
101 HttpServer::~HttpServer() {
102 STLDeleteContainerPairSecondPointers(connections_.begin(),
103 connections_.end());
104 }
105
106 void HttpServer::HandleRequest(HttpConnection* connection,
107 scoped_ptr<HttpRequest> request) {
108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
109
110 for (size_t i = 0; i < request_handlers_.size(); ++i) {
111 scoped_ptr<HttpResponse> response =
112 request_handlers_[i].Run(*request.get());
113 if (response.get()) {
114 connection->SendResponse(response.Pass());
115 return;
116 }
117 }
118
119 LOG(WARNING) << "Request not handled. Returning 404.";
120 scoped_ptr<HttpResponse> not_found_response(new HttpResponse());
121 not_found_response->code = NOT_FOUND;
122 connection->SendResponse(not_found_response.Pass());
123
124 // Drop the connection, since we do not support multiple requests per
125 // connection.
126 connections_.erase(connection->socket_.get());
127 delete connection;
128 }
129
130 GURL HttpServer::GetBaseURL() {
131 return base_url_;
132 }
133
134 void HttpServer::RegisterRequestHandler(
135 const HandleRequestCallback& callback) {
136 request_handlers_.push_back(callback);
137 }
138
139 GURL HttpServer::RegisterDefaultResponse(
140 const std::string& relative_path,
141 const HttpResponse& default_response) {
142 GURL request_url = base_url_.Resolve(relative_path);
143 const HandleRequestCallback callback =
144 base::Bind(&HandleDefaultRequest,
145 request_url,
146 default_response);
147 request_handlers_.push_back(callback);
148
149 return request_url;
150 }
151
152 GURL HttpServer::RegisterTextResponse(
153 const std::string& relative_path,
154 const std::string& content,
155 const std::string& content_type,
156 const ResponseCode response_code) {
157 HttpResponse default_response;
158 default_response.content = content;
159 default_response.content_type = content_type;
160 default_response.code = response_code;
161
162 return RegisterDefaultResponse(relative_path, default_response);
163 }
164
165 GURL HttpServer::RegisterFileResponse(
166 const std::string& relative_path,
167 const FilePath& file_path,
168 const std::string& content_type,
169 const ResponseCode response_code) {
170 HttpResponse default_response;
171
172 DCHECK(file_util::ReadFileToString(file_path, &default_response.content)) <<
Lei Zhang 2012/11/14 04:24:15 Again, is it ok if a release build did not read fi
satorux1 2012/11/14 04:43:36 Done. Good catch!
173 "Failed to open the file: " << file_path.value();
174
175 default_response.content_type = content_type;
176 default_response.code = response_code;
177
178 return RegisterDefaultResponse(relative_path, default_response);
179 }
180
181 void HttpServer::DidAccept(net::StreamListenSocket* server,
182 net::StreamListenSocket* connection) {
183 HttpConnection* http_connection = new HttpConnection(
184 connection,
185 base::Bind(&HttpServer::HandleRequest, weak_factory_.GetWeakPtr()));
186 connections_[connection] = http_connection;
187 }
188
189 void HttpServer::DidRead(net::StreamListenSocket* connection,
190 const char* data,
191 int length) {
192 HttpConnection* http_connection = FindConnection(connection);
193 if (http_connection == NULL) {
194 LOG(WARNING) << "Unknown connection.";
195 return;
196 }
197 http_connection->ReceiveData(std::string(data, length));
198 }
199
200 void HttpServer::DidClose(net::StreamListenSocket* connection) {
201 HttpConnection* http_connection = FindConnection(connection);
202 if (http_connection == NULL) {
203 LOG(WARNING) << "Unknown connection.";
204 return;
205 }
206 delete http_connection;
207 connections_.erase(connection);
208 }
209
210 HttpConnection* HttpServer::FindConnection(
211 net::StreamListenSocket* socket) {
212 std::map<net::StreamListenSocket*, HttpConnection*>::iterator it =
213 connections_.find(socket);
214 if (it == connections_.end()) {
215 return NULL;
216 }
217 return it->second;
218 }
219
220 } // namespace test_server
221 } // namespace drive
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698