OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 | 2 |
3 """ | 3 """ |
4 Copyright 2013 Google Inc. | 4 Copyright 2013 Google Inc. |
5 | 5 |
6 Use of this source code is governed by a BSD-style license that can be | 6 Use of this source code is governed by a BSD-style license that can be |
7 found in the LICENSE file. | 7 found in the LICENSE file. |
8 | 8 |
9 HTTP server for our HTML rebaseline viewer. | 9 HTTP server for our HTML rebaseline viewer. |
10 """ | 10 """ |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 self._url = 'http://%s:%d' % (host, http_server.server_port) | 253 self._url = 'http://%s:%d' % (host, http_server.server_port) |
254 logging.info('Listening for requests on %s' % self._url) | 254 logging.info('Listening for requests on %s' % self._url) |
255 http_server.serve_forever() | 255 http_server.serve_forever() |
256 | 256 |
257 | 257 |
258 class HTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): | 258 class HTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): |
259 """ HTTP request handlers for various types of queries this server knows | 259 """ HTTP request handlers for various types of queries this server knows |
260 how to handle (static HTML and Javascript, expected/actual results, etc.) | 260 how to handle (static HTML and Javascript, expected/actual results, etc.) |
261 """ | 261 """ |
262 def do_GET(self): | 262 def do_GET(self): |
263 """ Handles all GET requests, forwarding them to the appropriate | 263 """ |
264 do_GET_* dispatcher. """ | 264 Handles all GET requests, forwarding them to the appropriate |
265 if self.path == '' or self.path == '/' or self.path == '/index.html' : | 265 do_GET_* dispatcher. |
266 self.redirect_to('/static/index.html') | |
267 return | |
268 if self.path == '/favicon.ico' : | |
269 self.redirect_to('/static/favicon.ico') | |
270 return | |
271 | 266 |
272 # All requests must be of this form: | 267 If we see any Exceptions, return a 404. This fixes http://skbug.com/2147 |
273 # /dispatcher/remainder | 268 """ |
274 # where 'dispatcher' indicates which do_GET_* dispatcher to run | 269 try: |
275 # and 'remainder' is the remaining path sent to that dispatcher. | 270 logging.debug('do_GET: path="%s"' % self.path) |
276 normpath = posixpath.normpath(self.path) | 271 if self.path == '' or self.path == '/' or self.path == '/index.html' : |
277 (dispatcher_name, remainder) = PATHSPLIT_RE.match(normpath).groups() | 272 self.redirect_to('/static/index.html') |
278 dispatchers = { | 273 return |
279 'results': self.do_GET_results, | 274 if self.path == '/favicon.ico' : |
280 'static': self.do_GET_static, | 275 self.redirect_to('/static/favicon.ico') |
281 } | 276 return |
282 dispatcher = dispatchers[dispatcher_name] | 277 |
283 dispatcher(remainder) | 278 # All requests must be of this form: |
| 279 # /dispatcher/remainder |
| 280 # where 'dispatcher' indicates which do_GET_* dispatcher to run |
| 281 # and 'remainder' is the remaining path sent to that dispatcher. |
| 282 normpath = posixpath.normpath(self.path) |
| 283 (dispatcher_name, remainder) = PATHSPLIT_RE.match(normpath).groups() |
| 284 dispatchers = { |
| 285 'results': self.do_GET_results, |
| 286 'static': self.do_GET_static, |
| 287 } |
| 288 dispatcher = dispatchers[dispatcher_name] |
| 289 dispatcher(remainder) |
| 290 except: |
| 291 self.send_error(404) |
| 292 raise |
284 | 293 |
285 def do_GET_results(self, type): | 294 def do_GET_results(self, type): |
286 """ Handle a GET request for GM results. | 295 """ Handle a GET request for GM results. |
287 | 296 |
288 Args: | 297 Args: |
289 type: string indicating which set of results to return; | 298 type: string indicating which set of results to return; |
290 must be one of the results.RESULTS_* constants | 299 must be one of the results.RESULTS_* constants |
291 """ | 300 """ |
292 logging.debug('do_GET_results: sending results of type "%s"' % type) | 301 logging.debug('do_GET_results: sending results of type "%s"' % type) |
293 try: | 302 # Since we must make multiple calls to the Results object, grab a |
294 # Since we must make multiple calls to the Results object, grab a | 303 # reference to it in case it is updated to point at a new Results |
295 # reference to it in case it is updated to point at a new Results | 304 # object within another thread. |
296 # object within another thread. | 305 # |
297 # | 306 # TODO(epoger): Rather than using a global variable for the handler |
298 # TODO(epoger): Rather than using a global variable for the handler | 307 # to refer to the Server object, make Server a subclass of |
299 # to refer to the Server object, make Server a subclass of | 308 # HTTPServer, and then it could be available to the handler via |
300 # HTTPServer, and then it could be available to the handler via | 309 # the handler's .server instance variable. |
301 # the handler's .server instance variable. | 310 results_obj = _SERVER.results |
302 results_obj = _SERVER.results | 311 if results_obj: |
303 if results_obj: | 312 response_dict = self.package_results(results_obj, type) |
304 response_dict = self.package_results(results_obj, type) | 313 else: |
305 else: | 314 now = int(time.time()) |
306 now = int(time.time()) | 315 response_dict = { |
307 response_dict = { | 316 'header': { |
308 'header': { | 317 'resultsStillLoading': True, |
309 'resultsStillLoading': True, | 318 'timeUpdated': now, |
310 'timeUpdated': now, | 319 'timeNextUpdateAvailable': now + RELOAD_INTERVAL_UNTIL_READY, |
311 'timeNextUpdateAvailable': now + RELOAD_INTERVAL_UNTIL_READY, | 320 }, |
312 }, | 321 } |
313 } | 322 self.send_json_dict(response_dict) |
314 self.send_json_dict(response_dict) | |
315 except: | |
316 self.send_error(404) | |
317 raise | |
318 | 323 |
319 def package_results(self, results_obj, type): | 324 def package_results(self, results_obj, type): |
320 """ Given a nonempty "results" object, package it as a response_dict | 325 """ Given a nonempty "results" object, package it as a response_dict |
321 as needed within do_GET_results. | 326 as needed within do_GET_results. |
322 | 327 |
323 Args: | 328 Args: |
324 results_obj: nonempty "results" object | 329 results_obj: nonempty "results" object |
325 type: string indicating which set of results to return; | 330 type: string indicating which set of results to return; |
326 must be one of the results.RESULTS_* constants | 331 must be one of the results.RESULTS_* constants |
327 """ | 332 """ |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 'Attempted do_GET_static() of path [%s] outside of static dir [%s]' | 381 'Attempted do_GET_static() of path [%s] outside of static dir [%s]' |
377 % (full_path, static_dir)) | 382 % (full_path, static_dir)) |
378 self.send_error(404) | 383 self.send_error(404) |
379 | 384 |
380 def do_POST(self): | 385 def do_POST(self): |
381 """ Handles all POST requests, forwarding them to the appropriate | 386 """ Handles all POST requests, forwarding them to the appropriate |
382 do_POST_* dispatcher. """ | 387 do_POST_* dispatcher. """ |
383 # All requests must be of this form: | 388 # All requests must be of this form: |
384 # /dispatcher | 389 # /dispatcher |
385 # where 'dispatcher' indicates which do_POST_* dispatcher to run. | 390 # where 'dispatcher' indicates which do_POST_* dispatcher to run. |
| 391 logging.debug('do_POST: path="%s"' % self.path) |
386 normpath = posixpath.normpath(self.path) | 392 normpath = posixpath.normpath(self.path) |
387 dispatchers = { | 393 dispatchers = { |
388 '/edits': self.do_POST_edits, | 394 '/edits': self.do_POST_edits, |
389 } | 395 } |
390 try: | 396 try: |
391 dispatcher = dispatchers[normpath] | 397 dispatcher = dispatchers[normpath] |
392 dispatcher() | 398 dispatcher() |
393 self.send_response(200) | 399 self.send_response(200) |
394 except: | 400 except: |
395 self.send_error(404) | 401 self.send_error(404) |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
535 args = parser.parse_args() | 541 args = parser.parse_args() |
536 global _SERVER | 542 global _SERVER |
537 _SERVER = Server(actuals_dir=args.actuals_dir, | 543 _SERVER = Server(actuals_dir=args.actuals_dir, |
538 port=args.port, export=args.export, editable=args.editable, | 544 port=args.port, export=args.export, editable=args.editable, |
539 reload_seconds=args.reload) | 545 reload_seconds=args.reload) |
540 _SERVER.run() | 546 _SERVER.run() |
541 | 547 |
542 | 548 |
543 if __name__ == '__main__': | 549 if __name__ == '__main__': |
544 main() | 550 main() |
OLD | NEW |