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

Side by Side Diff: tools/OmahaCompatibility/HttpServer/http_server.cc

Issue 624713003: Keep only base/extractor.[cc|h]. (Closed) Base URL: https://chromium.googlesource.com/external/omaha.git@master
Patch Set: Created 6 years, 2 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
OLDNEW
(Empty)
1 // Copyright 2008-2009 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 // ========================================================================
15
16
17 #include "omaha/tools/omahacompatibility/httpserver/http_server.h"
18
19 #include <Windows.h>
20 #include <http.h>
21 #include <winhttp.h>
22 #include "omaha/common/error.h"
23 #include "omaha/common/debug.h"
24 #include "omaha/common/logging.h"
25 #include "omaha/common/string.h"
26 #include "omaha/common/utils.h"
27 #include "omaha/common/reg_key.h"
28
29 namespace omaha {
30
31 #define MAX_BUFFER_SIZE 4048
32 #define INTERNET_MAX_PATH_LENGTH 2048
33
34 HttpServer::HttpServer(const CString& host, int port)
35 : host_(host),
36 port_(port) {
37 CORE_LOG(L1, (_T("[HttpServer]")));
38 url_prefix_.Format(_T("http://%s:%d"), host, port);
39 }
40
41 HttpServer::~HttpServer() {
42 CORE_LOG(L1, (_T("[~HttpServer]")));
43 ::HttpTerminate(HTTP_INITIALIZE_SERVER, NULL);
44
45 std::map<CString, UrlHandler*>::iterator iter = handlers_.begin();
46 for (; iter != handlers_.end(); ++iter) {
47 std::pair<CString, UrlHandler*> pair = *iter;
48 VERIFY1(::HttpRemoveUrl(get(request_handle_),
49 pair.first) != NO_ERROR);
50 delete pair.second;
51 }
52
53 handlers_.clear();
54 }
55
56 HRESULT HttpServer::Initialize() {
57 CORE_LOG(L1, (_T("[Initialize]")));
58 HTTPAPI_VERSION version = HTTPAPI_VERSION_1;
59 int ret = ::HttpInitialize(version,
60 HTTP_INITIALIZE_SERVER,
61 NULL);
62 if (ret != NO_ERROR) {
63 return HRESULT_FROM_WIN32(ret);
64 }
65
66 ret = ::HttpCreateHttpHandle(address(request_handle_), NULL);
67 if (ret != NO_ERROR) {
68 return HRESULT_FROM_WIN32(ret);
69 }
70 ASSERT1(get(request_handle_));
71
72 return S_OK;
73 }
74
75 HRESULT HttpServer::AddUrlHandler(UrlHandler* handler) {
76 CORE_LOG(L1, (_T("[AddUrlHandler]")));
77 ASSERT1(handler);
78
79 CString full_url = url_prefix_ + handler->get_url_path();
80 int ret = ::HttpAddUrl(get(request_handle_),
81 full_url, NULL);
82 if (ret != NO_ERROR) {
83 return HRESULT_FROM_WIN32(ret);
84 }
85
86 ASSERT1(handlers_.find(handler->get_url_path()) == handlers_.end());
87 handlers_[handler->get_url_path()] = handler;
88 return S_OK;
89 }
90
91 UrlHandler* HttpServer::GetHandler(const HttpRequest& req) {
92 std::map<CString, UrlHandler*>::const_iterator iter = handlers_.begin();
93 for (; iter != handlers_.end(); ++iter) {
94 UrlHandler* handler = (*iter).second;
95
96 // Determine if the handler starts with the path that is specified
97 // in the request.
98 if (req.path().Find(handler->get_url_path()) == 0) {
99 return handler;
100 }
101 }
102
103 ASSERT1(false);
104 return NULL;
105 }
106
107 HRESULT HttpServer::ReadRequest(HttpRequest* request) {
108 ASSERT1(request);
109
110 TCHAR buffer[MAX_BUFFER_SIZE] = {0};
111 HTTP_REQUEST* req = reinterpret_cast<HTTP_REQUEST*>(buffer);
112 int ret = ::HttpReceiveHttpRequest(get(request_handle_),
113 HTTP_NULL_ID,
114 HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY,
115 req,
116 MAX_BUFFER_SIZE,
117 NULL,
118 NULL);
119
120 if (ret != NO_ERROR) {
121 HRESULT hr = HRESULT_FROM_WIN32(ret);
122 CORE_LOG(L1, (_T("[Failed to read request.][0x%08x]"), hr));
123 return hr;
124 }
125
126 // Figure out the query string and the path.
127 CString url_path(req->pRawUrl);
128 int idx = url_path.ReverseFind(_T('?'));
129 CString query_str;
130 CString path;
131 if (idx != -1) {
132 query_str = url_path.Right(url_path.GetLength() - idx - 1);
133 path = url_path.Left(idx);
134 } else {
135 path = url_path;
136 }
137
138 // Set the values on the request.
139 request->set_http_verb(req->Verb);
140 request->set_path(path);
141 request->set_http_request(*req);
142 request->set_query_str(query_str);
143
144 if (req->Verb == HttpVerbPOST) {
145 DWORD bytes_received = 0;
146 char output_buffer[MAX_BUFFER_SIZE] = {0};
147 ret = ::HttpReceiveRequestEntityBody(get(request_handle_),
148 req->RequestId,
149 0,
150 output_buffer,
151 MAX_BUFFER_SIZE,
152 &bytes_received,
153 NULL);
154
155 if (ret != NO_ERROR) {
156 HRESULT hr = HRESULT_FROM_WIN32(ret);
157 CORE_LOG(L1, (_T("[Failed to read request.][0x%08x]"), hr));
158 return hr;
159 }
160 CString content = Utf8ToWideChar(output_buffer, bytes_received);
161 request->set_content(content);
162 }
163
164 return S_OK;
165 }
166
167 HRESULT HttpServer::SetHeader(HTTP_RESPONSE* http_response,
168 HTTP_HEADER_ID header_id,
169 const char* value) {
170 ASSERT1(http_response);
171
172 http_response->Headers.KnownHeaders[header_id].pRawValue = value;
173 http_response->Headers.KnownHeaders[header_id].RawValueLength =
174 static_cast<USHORT>(strlen(value));
175 return S_OK;
176 }
177
178 HRESULT HttpServer::SendResponse(const HttpResponse& response) {
179 const HttpRequest& request = response.request();
180 const char* const kOk = "OK";
181
182 HTTP_RESPONSE http_response = {0};
183 http_response.StatusCode = 200;
184
185 // Send back an ok.
186 http_response.pReason = kOk;
187 http_response.ReasonLength = static_cast<USHORT>(strlen(kOk));
188
189 // No special headers for now.
190 HTTP_RESPONSE_HEADERS headers = {0};
191 headers.UnknownHeaderCount = 0;
192 headers.TrailerCount = 0;
193 http_response.Headers = headers;
194
195 scoped_hfile handle;
196 CStringA request_body_utf8;
197 CStringA content_range_header;
198 int http_response_flag = 0;
199
200 HTTP_DATA_CHUNK chunk;
201 memset(&chunk, 0, sizeof(HTTP_DATA_CHUNK));
202
203 // Based on the verb build a response.
204 if (request.http_verb() == HttpVerbPOST) {
205 // Add a known header of content type.
206 SetHeader(&http_response, HttpHeaderContentType, "text/xml; charset=UTF-8");
207
208 // Send back the content.
209 chunk.DataChunkType = HttpDataChunkFromMemory;
210 CString response_str = response.response_str();
211 request_body_utf8 = CT2A(response_str, CP_UTF8);
212
213 chunk.FromMemory.pBuffer = request_body_utf8.GetBuffer();
214 chunk.FromMemory.BufferLength = request_body_utf8.GetLength();
215
216 http_response.EntityChunkCount = 1;
217 http_response.pEntityChunks = &chunk;
218
219 } else if (request.http_verb() == HttpVerbHEAD) {
220 // Add the content length, type, and content range headers.
221 SetHeader(&http_response, HttpHeaderContentType,
222 "application/octet-stream");
223 char size_str[MAX_PATH] = {0};
224 _itoa(response.size(), size_str, 10);
225 SetHeader(&http_response, HttpHeaderContentLength, size_str);
226 SetHeader(&http_response, HttpHeaderAcceptRanges, "bytes");
227
228 } else if (request.http_verb() == HttpVerbGET) {
229 SetHeader(&http_response, HttpHeaderContentType,
230 "application/octet-stream");
231 char size_str[MAX_PATH] = {0};
232 _itoa(response.size(), size_str, 10);
233 SetHeader(&http_response, HttpHeaderAcceptRanges, "bytes");
234
235 reset(handle, ::CreateFile(response.file_name(), GENERIC_READ,
236 FILE_SHARE_READ, NULL, OPEN_EXISTING,
237 FILE_ATTRIBUTE_NORMAL, NULL));
238 if (!handle) {
239 return HRESULTFromLastError();
240 }
241
242 chunk.DataChunkType = HttpDataChunkFromFileHandle;
243
244 // Determine the file portion to send back to the client.
245 // If the client has sent a range request, honor that.
246 int start_file_pos = 0;
247 int end_file_pos = 0;
248 HTTP_REQUEST tmp_request = request.http_request();
249 if (tmp_request.Headers.KnownHeaders[HttpHeaderRange].RawValueLength != 0) {
250 // The client send a content length header. We need to honor this.
251 CStringA content_range(
252 tmp_request.Headers.KnownHeaders[HttpHeaderRange].pRawValue);
253
254 int idx = content_range.Find('-');
255 ASSERT1(idx != -1);
256 end_file_pos = atoi(content_range.Right(
257 content_range.GetLength() - idx - 1));
258 int st_idx = content_range.Find('=');
259 ASSERT1(st_idx != -1);
260 start_file_pos = atoi(content_range.Mid(st_idx + 1, idx));
261
262 // Set the Content-range header in the response.
263 content_range_header.Format("bytes %d-%d/%d",
264 start_file_pos,
265 end_file_pos, response.size());
266 SetHeader(&http_response, HttpHeaderContentRange, content_range_header);
267
268 // Since this is a range request, we set the http response code to
269 // partial response.
270 http_response.StatusCode = 206;
271
272 // Set the value of the human readable text to partial-content.
273 const char* const kPartialContent = "Partial Content";
274 http_response.pReason = kPartialContent;
275 http_response.ReasonLength = static_cast<USHORT>(strlen(kPartialContent));
276 }
277
278 // Send back the entire file or part of it.
279 HTTP_BYTE_RANGE byte_range = {0};
280 byte_range.StartingOffset.HighPart = 0;
281 byte_range.StartingOffset.LowPart = start_file_pos;
282 if (end_file_pos == 0) {
283 byte_range.Length.QuadPart = HTTP_BYTE_RANGE_TO_EOF;
284 } else {
285 byte_range.Length.QuadPart = end_file_pos - start_file_pos + 1;
286 }
287
288 chunk.FromFileHandle.ByteRange = byte_range;
289 chunk.FromFileHandle.FileHandle = get(handle);
290
291 http_response.EntityChunkCount = 1;
292 http_response.pEntityChunks = &chunk;
293 }
294
295 DWORD bytes_sent = 0;
296 int ret = ::HttpSendHttpResponse(
297 get(request_handle_),
298 request.http_request().RequestId,
299 http_response_flag,
300 &http_response,
301 NULL,
302 &bytes_sent,
303 NULL,
304 0,
305 NULL,
306 NULL);
307 if (ret != NO_ERROR) {
308 return HRESULT_FROM_WIN32(ret);
309 }
310
311 return S_OK;
312 }
313
314 HRESULT HttpServer::Start() {
315 CORE_LOG(L1, (_T("[Start]")));
316
317 while (true) {
318 HttpRequest request;
319 HRESULT hr = ReadRequest(&request);
320 if (FAILED(hr)) {
321 CORE_LOG(L1, (_T("[ReadRequest failed.][0x%08x]"), hr));
322 continue;
323 }
324
325 HttpResponse response(request);
326 UrlHandler* handler = GetHandler(request);
327 if (handler == NULL) {
328 continue;
329 }
330
331 hr = handler->HandleRequest(request, &response);
332 if (FAILED(hr)) {
333 CORE_LOG(L1, (_T("[HandlerRequest failed.][0x%08x]"), hr));
334 continue;
335 }
336
337 hr = SendResponse(response);
338 if (FAILED(hr)) {
339 CORE_LOG(L1, (_T("[SendRequest failed.][0x%08x]"), hr));
340 continue;
341 }
342 }
343
344 return S_OK;
345 }
346
347 } // namespace omaha
OLDNEW
« no previous file with comments | « tools/OmahaCompatibility/HttpServer/http_server.h ('k') | tools/OmahaCompatibility/HttpServer/response.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698