import os
import proxyshaper
import re
+import socket
import SocketServer
import ssl
import subprocess
logging.error('Error sending response for %s%s: %s',
self.headers['host'], self.path, e)
- def _manage_request_count(fn):
- """Keep track of the current number active requests.
+ def handle_one_request(self):
+ """Handle a single HTTP request."""
+ try:
+ self.raw_requestline = self.rfile.readline(65537)
+ self.do_parse_and_handle_one_request()
+ except socket.timeout, e:
+ # A read or a write timed out. Discard this connection
+ self.log_error("Request timed out: %r", e)
+ self.close_connection = 1
+ return
+
+ def do_parse_and_handle_one_request(self):
+ start_time = time.time()
+ self.server.num_active_requests += 1
+ request = None
+ try:
+ if len(self.raw_requestline) > 65536:
+ self.requestline = ''
+ self.request_version = ''
+ self.command = ''
+ self.send_error(414)
+ return
+ if not self.raw_requestline:
+ self.close_connection = 1
+ return
+ if not self.parse_request():
+ # An error code has been sent, just exit
+ return
- This is used for traffic shaping. The request and response are
- wrapped separately because no single BaseHTTPRequestHandler
- function handles an entire active request.
- BaseHTTPRequestHandler.process_one_request() does not work because
- when one request finishes it is called again to wait for another
- request -- and another request may never arrive.
- """
- def wrapped(self, *args, **kwargs):
- self.server.num_active_requests += 1
try:
- return fn(self, *args, **kwargs)
+ request = self.get_archived_http_request()
+ if request is None:
+ self.send_error(500)
+ return
+ response = self.server.custom_handlers.handle(request)
+ if not response:
+ response = self.server.http_archive_fetch(request)
+ if response:
+ self.send_archived_http_response(response)
+ else:
+ self.send_error(404)
finally:
- self.server.num_active_requests -= 1
- return wrapped
-
- @_manage_request_count
- def parse_request(self):
- return BaseHTTPServer.BaseHTTPRequestHandler.parse_request(self)
-
- def do_POST(self):
- self.do_GET()
-
- def do_HEAD(self):
- self.do_GET()
-
- @_manage_request_count
- def do_GET(self):
- start_time = time.time()
- request = self.get_archived_http_request()
- if request is None:
- self.send_error(500)
- return
- response = self.server.custom_handlers.handle(request)
- if not response:
- response = self.server.http_archive_fetch(request)
- if response:
- self.send_archived_http_response(response)
+ self.wfile.flush() # Actually send the response if not already done.
+ finally:
request_time_ms = (time.time() - start_time) * 1000.0;
- logging.debug('Served: %s (%dms)', request, request_time_ms)
+ if request:
+ logging.debug('Served: %s (%dms)', request, request_time_ms)
self.server.total_request_time += request_time_ms
- else:
- self.send_error(404)
+ self.server.num_active_requests -= 1
def send_error(self, status, body=None):
"""Override the default send error with a version that doesn't unnecessarily