Suppression for crbug/241044.
[chromium-blink-merge.git] / chrome / test / install_test / chrome_proxy_server.py
blobb9d7ec9a55f215902c618815a0cd76aa7074b82b
1 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 """A simple HTTP proxy server."""
7 import BaseHTTPServer
8 import copy
9 import os
10 import socket
11 import SocketServer
12 import threading
13 import urllib
14 import urllib2
15 from urlparse import urlparse
17 _HOST = '127.0.0.1'
20 class _ProxyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
21 """Request handler for the proxy server."""
23 # Disables buffering, which causes problems with certain sites.
24 rbufsize = 0
26 def __init__(self, request, client_addr, server):
27 BaseHTTPServer.BaseHTTPRequestHandler.__init__(
28 self, request, client_addr, server)
30 def _GetHandler(self):
31 """GET handler for requests that will be processed by the server."""
32 try:
33 url = urllib.urlopen(self.path, proxies={'http:' : '127.0.0.1'})
34 except IOError, err:
35 self.wfile.write(err)
36 return
37 data = url.read()
38 self.wfile.write(data)
39 url.close()
41 def do_GET(self):
42 """Handles GET requests."""
43 if self._ShouldHandleRequest():
44 self._LogRequest()
45 self._GetHandler()
46 else:
47 self._GenericResponseHandler()
49 def do_CONNECT(self):
50 """Handles CONNECT requests."""
51 self._GenericResponseHandler()
53 def do_HEAD(self):
54 """Handles HEAD requests."""
55 self.do_GET()
57 def do_POST(self):
58 """Handles POST requests."""
59 self.do_GET()
61 def do_PUT(self):
62 """Handles PUT requests."""
63 self.do_GET()
65 def _GenericResponseHandler(self):
66 """Sends a dummy reponse for HTTP requests not handled by the server."""
67 # Handle dropped connections.
68 try:
69 self.send_response(200)
70 except (socket.error, socket.gaierror):
71 return
72 contents = 'Default response given for path: %s' % self.path
73 self.send_header('Content-Type', 'text/html')
74 self.send_header('Content-Length', len(contents))
75 self.end_headers()
76 if (self.command != 'HEAD'):
77 self.wfile.write(contents)
79 def _ShouldHandleRequest(self):
80 """Determines if a request should be processed by the server."""
81 if self.server.ShouldHandleAllRequests():
82 return True
83 (scheme, netloc, path, params, query, flag) = urlparse(self.path, 'http')
84 paths = self.server.GetPaths()
85 if(any([netloc.find(url) >= 0 for url in paths]) or
86 any([self.path.find(url) >= 0 for url in paths])):
87 return True
88 return False
90 def _LogRequest(self):
91 """Logs requests handled by the server to a buffer."""
92 self.server.AddHandledRequest(self.requestline)
94 def log_request(self, *args, **kwargs):
95 """Overridden base class method that disables request logging."""
96 pass
99 class ProxyServer(SocketServer.ThreadingMixIn, BaseHTTPServer.HTTPServer):
100 """Creates a threaded proxy server."""
102 def __init__(self, port=0, paths=[], handle_all=True):
103 """Initializes proxy server settings.
105 Args:
106 port: Server port number. If zero, the server will select a free port.
107 paths: A list containing urls the server will process. If |handle_all| is
108 False, the server will only process urls in this list. URLs should be
109 passed as follows: ['http://www.google.com', '...',].
110 handle_all: Flag that determines if the server will process all requests.
112 BaseHTTPServer.HTTPServer.__init__(
113 self, (_HOST, port), _ProxyRequestHandler, True)
114 self._stopped = False
115 self._serving = False
116 self._lock = threading.RLock()
117 self._paths = list(paths)
118 self._handle_all = handle_all
119 self._handled_requests = []
120 self.StartServer()
122 def GetPort(self):
123 """Returns the port number the server is serving on."""
124 return self.server_port
126 def StartServer(self):
127 """Starts the proxy server in a new thread."""
128 if self._stopped:
129 raise RuntimeError('Cannot restart server.')
130 if not self._serving:
131 self._serving = True
132 thread = WorkerThread(self)
133 thread.start()
135 def Shutdown(self):
136 """Shuts down the server."""
137 if not self._serving:
138 raise RuntimeError('Server is currently inactive.')
139 self._serving = False
140 self._stopped = True
141 try:
142 urllib2.urlopen('http://%s:%s' % (self.server_name, self.server_port))
143 except urllib2.URLError:
144 pass
145 self.server_close()
147 def handle_request(self):
148 """Handles requests while the |_serving| flag is True."""
149 while self._serving:
150 BaseHTTPServer.HTTPServer.handle_request(self)
152 def ShouldHandleAllRequests(self):
153 """Determines if server should handle all requests."""
154 return self._handle_all
156 def AddHandledRequest(self, request):
157 """Appends requests handled by the server to |_handled_requests|."""
158 try:
159 self._lock.acquire()
160 self._handled_requests.append(request)
161 finally:
162 self._lock.release()
164 def GetHandledRequests(self):
165 """Returns requests handled by the server."""
166 try:
167 self._lock.acquire()
168 return copy.deepcopy(self._handled_requests)
169 finally:
170 self._lock.release()
172 def GetPaths(self):
173 """Returns list of urls that will be handled by the server."""
174 return self._paths
177 class WorkerThread(threading.Thread):
178 """Creates a worker thread."""
180 def __init__(self, server):
181 threading.Thread.__init__(self)
182 self._server = server
184 def run(self):
185 """Overridden base class method."""
186 print 'Serving on port: %s' % self._server.server_port
187 self._server.daemon_threads = True
188 self._server.handle_request()