| Index: tools/playback_benchmark/proxy_handler.py
|
| ===================================================================
|
| --- tools/playback_benchmark/proxy_handler.py (revision 0)
|
| +++ tools/playback_benchmark/proxy_handler.py (revision 0)
|
| @@ -0,0 +1,123 @@
|
| +#!/usr/bin/env python
|
| +#
|
| +# Copyright 2010 Google Inc. All Rights Reserved.
|
| +
|
| +"""HTTP proxy request handler with SSL support.
|
| +
|
| + RequestHandler: Utility class for parsing HTTP requests.
|
| + ProxyHandler: HTTP proxy handler.
|
| +"""
|
| +
|
| +import BaseHTTPServer
|
| +import cgi
|
| +import OpenSSL
|
| +import os
|
| +import socket
|
| +import SocketServer
|
| +import sys
|
| +import traceback
|
| +import urlparse
|
| +
|
| +
|
| +class RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
| + """Class for reading HTTP requests and writing HTTP responses"""
|
| +
|
| + protocol_version = "HTTP/1.1"
|
| + request_version = protocol_version
|
| +
|
| + class HTTPRequestException(Exception): pass
|
| +
|
| + def __init__(self, rfile, wfile, server):
|
| + self.rfile = rfile
|
| + self.wfile = wfile
|
| + self.server = server
|
| +
|
| + def ReadRequest(self):
|
| + "Reads and parses single HTTP request from self.rfile"
|
| +
|
| + self.raw_requestline = self.rfile.readline()
|
| + if not self.raw_requestline:
|
| + self.close_connection = 1
|
| + raise HTTPRequestException('failed to read request line')
|
| + if not self.parse_request():
|
| + raise HTTPRequestException('failed to parse request')
|
| + self.headers = dict(self.headers)
|
| + self.body = None
|
| + if 'content-length' in self.headers:
|
| + self.body = self.rfile.read(int(self.headers['content-length']))
|
| +
|
| + def log_message(self, format, *args):
|
| + pass
|
| +
|
| +
|
| +class ProxyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
| + "Request handler class for proxy server"
|
| +
|
| + server_version = "PlaybackProxy/0.0.1"
|
| + protocol_version = "HTTP/1.1"
|
| +
|
| + def do_CONNECT(self):
|
| + "Handles CONNECT HTTP request"
|
| +
|
| + server = self.path.split(':')[0]
|
| + certificate_file = os.path.join(self.certificate_directory, server)
|
| + if not os.path.isfile(certificate_file):
|
| + sys.stderr.write('request to connect %s is ignored\n' % server)
|
| + self.send_response(501)
|
| + self.send_header('Proxy-agent', self.version_string())
|
| + self.end_headers()
|
| + return
|
| +
|
| + # Send confirmation to browser.
|
| + self.send_response(200, 'Connection established')
|
| + self.send_header('Proxy-agent', self.version_string())
|
| + self.end_headers()
|
| +
|
| + # Create SSL context.
|
| + context = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD)
|
| + context.use_privatekey_file(certificate_file)
|
| + context.use_certificate_file(certificate_file)
|
| +
|
| + # Create and initialize SSL connection atop of tcp socket.
|
| + ssl_connection = OpenSSL.SSL.Connection(context, self.connection)
|
| + ssl_connection.set_accept_state()
|
| + ssl_connection.do_handshake()
|
| + ssl_rfile = socket._fileobject(ssl_connection, "rb", self.rbufsize)
|
| + ssl_wfile = socket._fileobject(ssl_connection, "wb", self.wbufsize)
|
| +
|
| + # Handle http requests coming from ssl_connection.
|
| + handler = RequestHandler(ssl_rfile, ssl_wfile, self.path)
|
| + try:
|
| + handler.close_connection = 1
|
| + while True:
|
| + handler.ReadRequest()
|
| + self.driver.ProcessRequest(handler)
|
| + if handler.close_connection: break
|
| + except (OpenSSL.SSL.SysCallError, OpenSSL.SSL.ZeroReturnError):
|
| + pass
|
| + finally:
|
| + self.close_connection = 1
|
| +
|
| + def do_GET(self):
|
| + self.driver.ProcessRequest(self)
|
| +
|
| + def do_POST(self):
|
| + if 'content-length' in self.headers:
|
| + self.body = self.rfile.read(int(self.headers['content-length']))
|
| + self.driver.ProcessRequest(self)
|
| +
|
| + def log_message(self, format, *args):
|
| + sys.stdout.write((format % args) + '\n')
|
| +
|
| +
|
| +class ThreadingHTTPServer (SocketServer.ThreadingMixIn,
|
| + BaseHTTPServer.HTTPServer):
|
| + pass
|
| +
|
| +
|
| +def CreateServer(driver, port, certificate_directory=None):
|
| + if not certificate_directory:
|
| + certificate_directory = os.path.join(os.getcwd(), 'certificates')
|
| + ProxyHandler.driver = driver
|
| + ProxyHandler.certificate_directory = certificate_directory
|
| + return ThreadingHTTPServer(('', port), ProxyHandler)
|
|
|