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

Side by Side Diff: test_http_server.cc

Issue 3161041: AU: Support redirects. (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/update_engine.git
Patch Set: reorder headers again Created 10 years, 3 months 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 | Annotate | Revision Log
« no previous file with comments | « libcurl_http_fetcher.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium OS Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // This file implements a simple HTTP server. It can exhibit odd behavior 5 // This file implements a simple HTTP server. It can exhibit odd behavior
6 // that's useful for testing. For example, it's useful to test that 6 // that's useful for testing. For example, it's useful to test that
7 // the updater can continue a connection if it's dropped, or that it 7 // the updater can continue a connection if it's dropped, or that it
8 // handles very slow data transfers. 8 // handles very slow data transfers.
9 9
10 // To use this, simply make an HTTP connection to localhost:port and 10 // To use this, simply make an HTTP connection to localhost:port and
(...skipping 14 matching lines...) Expand all
25 #include "base/logging.h" 25 #include "base/logging.h"
26 26
27 using std::min; 27 using std::min;
28 using std::string; 28 using std::string;
29 using std::vector; 29 using std::vector;
30 30
31 namespace chromeos_update_engine { 31 namespace chromeos_update_engine {
32 32
33 struct HttpRequest { 33 struct HttpRequest {
34 HttpRequest() : offset(0), return_code(200) {} 34 HttpRequest() : offset(0), return_code(200) {}
35 string host;
35 string url; 36 string url;
36 off_t offset; 37 off_t offset;
37 int return_code; 38 int return_code;
38 }; 39 };
39 40
40 namespace { 41 namespace {
41 const int kPort = 8080; // hardcoded to 8080 for now 42 const int kPort = 8080; // hardcoded to 8080 for now
42 const int kBigLength = 100000; 43 const int kBigLength = 100000;
44 const int kMediumLength = 1000;
43 } 45 }
44 46
45 bool ParseRequest(int fd, HttpRequest* request) { 47 bool ParseRequest(int fd, HttpRequest* request) {
46 string headers; 48 string headers;
47 while(headers.find("\r\n\r\n") == string::npos) { 49 while(headers.find("\r\n\r\n") == string::npos) {
48 vector<char> buf(1024); 50 vector<char> buf(1024);
49 memset(&buf[0], 0, buf.size()); 51 memset(&buf[0], 0, buf.size());
50 ssize_t r = read(fd, &buf[0], buf.size() - 1); 52 ssize_t r = read(fd, &buf[0], buf.size() - 1);
51 if (r < 0) { 53 if (r < 0) {
52 perror("read"); 54 perror("read");
53 exit(1); 55 exit(1);
54 } 56 }
55 buf.resize(r); 57 buf.resize(r);
56 58
57 headers.insert(headers.end(), buf.begin(), buf.end()); 59 headers.insert(headers.end(), buf.begin(), buf.end());
58 } 60 }
59 LOG(INFO) << "got headers: " << headers; 61 LOG(INFO) << "got headers: " << headers;
60 62
61 string::size_type url_start, url_end; 63 string::size_type url_start, url_end;
62 CHECK_NE(headers.find("GET "), string::npos); 64 CHECK_NE(headers.find("GET "), string::npos);
63 url_start = headers.find("GET ") + strlen("GET "); 65 url_start = headers.find("GET ") + strlen("GET ");
64 url_end = headers.find(' ', url_start); 66 url_end = headers.find(' ', url_start);
65 CHECK_NE(string::npos, url_end); 67 CHECK_NE(string::npos, url_end);
66 string url = headers.substr(url_start, url_end - url_start); 68 string url = headers.substr(url_start, url_end - url_start);
67 LOG(INFO) << "URL: " << url; 69 LOG(INFO) << "URL: " << url;
70 request->url = url;
68 71
69 string::size_type range_start, range_end; 72 string::size_type range_start, range_end;
70 if (headers.find("\r\nRange: ") == string::npos) { 73 if (headers.find("\r\nRange: ") == string::npos) {
71 request->offset = 0; 74 request->offset = 0;
72 } else { 75 } else {
73 range_start = headers.find("\r\nRange: ") + strlen("\r\nRange: "); 76 range_start = headers.find("\r\nRange: ") + strlen("\r\nRange: ");
74 range_end = headers.find('\r', range_start); 77 range_end = headers.find('\r', range_start);
75 CHECK_NE(string::npos, range_end); 78 CHECK_NE(string::npos, range_end);
76 string range_header = headers.substr(range_start, range_end - range_start); 79 string range_header = headers.substr(range_start, range_end - range_start);
77 80
78 LOG(INFO) << "Range: " << range_header; 81 LOG(INFO) << "Range: " << range_header;
79 CHECK(*range_header.rbegin() == '-'); 82 CHECK(*range_header.rbegin() == '-');
80 request->offset = atoll(range_header.c_str() + strlen("bytes=")); 83 request->offset = atoll(range_header.c_str() + strlen("bytes="));
81 request->return_code = 206; // Success for Range: request 84 request->return_code = 206; // Success for Range: request
82 LOG(INFO) << "Offset: " << request->offset; 85 LOG(INFO) << "Offset: " << request->offset;
83 } 86 }
84 request->url = url; 87
88 if (headers.find("\r\nHost: ") == string::npos) {
89 request->host = "";
90 } else {
91 string::size_type host_start =
92 headers.find("\r\nHost: ") + strlen("\r\nHost: ");
93 string::size_type host_end = headers.find('\r', host_start);
94 CHECK_NE(string::npos, host_end);
95 string host = headers.substr(host_start, host_end - host_start);
96
97 LOG(INFO) << "Host: " << host;
98 request->host = host;
99 }
100
85 return true; 101 return true;
86 } 102 }
87 103
88 void WriteString(int fd, const string& str) { 104 void WriteString(int fd, const string& str) {
89 unsigned int bytes_written = 0; 105 unsigned int bytes_written = 0;
90 while (bytes_written < str.size()) { 106 while (bytes_written < str.size()) {
91 ssize_t r = write(fd, str.c_str() + bytes_written, 107 ssize_t r = write(fd, str.c_str() + bytes_written,
92 str.size() - bytes_written); 108 str.size() - bytes_written);
93 LOG(INFO) << "write() wrote " << r << " bytes"; 109 LOG(INFO) << "write() wrote " << r << " bytes";
94 if (r < 0) { 110 if (r < 0) {
(...skipping 26 matching lines...) Expand all
121 content_length -= start_offset; 137 content_length -= start_offset;
122 WriteString(fd, string("Content-Length: ") + Itoa(content_length) + "\r\n"); 138 WriteString(fd, string("Content-Length: ") + Itoa(content_length) + "\r\n");
123 WriteString(fd, "\r\n"); 139 WriteString(fd, "\r\n");
124 } 140 }
125 141
126 void HandleQuitQuitQuit(int fd) { 142 void HandleQuitQuitQuit(int fd) {
127 WriteHeaders(fd, true, 0, 0, 200); 143 WriteHeaders(fd, true, 0, 0, 200);
128 exit(0); 144 exit(0);
129 } 145 }
130 146
131 void HandleBig(int fd, const HttpRequest& request) { 147 void HandleBig(int fd, const HttpRequest& request, int big_length) {
132 const off_t full_length = kBigLength; 148 const off_t full_length = big_length;
133 WriteHeaders(fd, true, full_length, request.offset, request.return_code); 149 WriteHeaders(fd, true, full_length, request.offset, request.return_code);
134 const off_t content_length = full_length - request.offset; 150 const off_t content_length = full_length - request.offset;
135 int i = request.offset; 151 int i = request.offset;
136 for (; i % 10; i++) 152 for (; i % 10; i++)
137 WriteString(fd, string(1, 'a' + (i % 10))); 153 WriteString(fd, string(1, 'a' + (i % 10)));
138 CHECK_EQ(i % 10, 0); 154 CHECK_EQ(i % 10, 0);
139 for (; i < content_length; i += 10) 155 for (; i < content_length; i += 10)
140 WriteString(fd, "abcdefghij"); 156 WriteString(fd, "abcdefghij");
141 CHECK_EQ(i, full_length); 157 CHECK_EQ(i, full_length);
142 } 158 }
(...skipping 23 matching lines...) Expand all
166 string::size_type half_way_point = buf.size() / 2; 182 string::size_type half_way_point = buf.size() / 2;
167 LOG(INFO) << "writing small data blob of size " << half_way_point; 183 LOG(INFO) << "writing small data blob of size " << half_way_point;
168 WriteString(fd, buf.substr(0, half_way_point)); 184 WriteString(fd, buf.substr(0, half_way_point));
169 sleep(10); 185 sleep(10);
170 LOG(INFO) << "writing small data blob of size " 186 LOG(INFO) << "writing small data blob of size "
171 << (buf.size() - half_way_point); 187 << (buf.size() - half_way_point);
172 WriteString(fd, buf.substr(half_way_point, buf.size() - half_way_point)); 188 WriteString(fd, buf.substr(half_way_point, buf.size() - half_way_point));
173 } 189 }
174 } 190 }
175 191
192 // Handles /redirect/<code>/<url> requests by returning the specified
193 // redirect <code> with a location pointing to /<url>.
194 void HandleRedirect(int fd, const HttpRequest& request) {
195 LOG(INFO) << "Redirecting...";
196 string url = request.url;
197 CHECK_EQ(0, url.find("/redirect/"));
198 url.erase(0, strlen("/redirect/"));
199 string::size_type url_start = url.find('/');
200 CHECK_NE(url_start, string::npos);
201 string code = url.substr(0, url_start);
202 url.erase(0, url_start);
203 url = "http://" + request.host + url;
204 string status;
205 if (code == "301") {
206 status = "Moved Permanently";
207 } else if (code == "302") {
208 status = "Found";
209 } else if (code == "303") {
210 status = "See Other";
211 } else if (code == "307") {
212 status = "Temporary Redirect";
213 } else {
214 CHECK(false) << "Unrecognized redirection code: " << code;
215 }
216 LOG(INFO) << "Code: " << code << " " << status;
217 LOG(INFO) << "New URL: " << url;
218 WriteString(fd, "HTTP/1.1 " + code + " " + status + "\r\n");
219 WriteString(fd, "Location: " + url + "\r\n");
220 }
221
176 void HandleDefault(int fd, const HttpRequest& request) { 222 void HandleDefault(int fd, const HttpRequest& request) {
177 const string data("unhandled path"); 223 const string data("unhandled path");
178 WriteHeaders(fd, true, data.size(), request.offset, request.return_code); 224 WriteHeaders(fd, true, data.size(), request.offset, request.return_code);
179 const string data_to_write(data.substr(request.offset, 225 const string data_to_write(data.substr(request.offset,
180 data.size() - request.offset)); 226 data.size() - request.offset));
181 WriteString(fd, data_to_write); 227 WriteString(fd, data_to_write);
182 } 228 }
183 229
184 void HandleConnection(int fd) { 230 void HandleConnection(int fd) {
185 HttpRequest request; 231 HttpRequest request;
186 ParseRequest(fd, &request); 232 ParseRequest(fd, &request);
187 233
188 if (request.url == "/quitquitquit") 234 if (request.url == "/quitquitquit")
189 HandleQuitQuitQuit(fd); 235 HandleQuitQuitQuit(fd);
190 else if (request.url == "/big") 236 else if (request.url == "/big")
191 HandleBig(fd, request); 237 HandleBig(fd, request, kBigLength);
238 else if (request.url == "/medium")
239 HandleBig(fd, request, kMediumLength);
192 else if (request.url == "/flaky") 240 else if (request.url == "/flaky")
193 HandleFlaky(fd, request); 241 HandleFlaky(fd, request);
242 else if (request.url.find("/redirect/") == 0)
243 HandleRedirect(fd, request);
194 else 244 else
195 HandleDefault(fd, request); 245 HandleDefault(fd, request);
196 246
197 close(fd); 247 close(fd);
198 } 248 }
199 249
200 } // namespace chromeos_update_engine 250 } // namespace chromeos_update_engine
201 251
202 using namespace chromeos_update_engine; 252 using namespace chromeos_update_engine;
203 253
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 int client_fd = accept(listen_fd, 287 int client_fd = accept(listen_fd,
238 (struct sockaddr *) &client_addr, 288 (struct sockaddr *) &client_addr,
239 &clilen); 289 &clilen);
240 LOG(INFO) << "got past accept"; 290 LOG(INFO) << "got past accept";
241 if (client_fd < 0) 291 if (client_fd < 0)
242 LOG(FATAL) << "ERROR on accept"; 292 LOG(FATAL) << "ERROR on accept";
243 HandleConnection(client_fd); 293 HandleConnection(client_fd);
244 } 294 }
245 return 0; 295 return 0;
246 } 296 }
OLDNEW
« no previous file with comments | « libcurl_http_fetcher.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698