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

Side by Side Diff: third_party/twisted_8_1/twisted/web/test/test_proxy.py

Issue 12261012: Remove third_party/twisted_8_1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Created 7 years, 10 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 # Copyright (c) 2007 Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4 """
5 Test for L{twisted.web.proxy}.
6 """
7
8 from twisted.trial.unittest import TestCase
9 from twisted.test.proto_helpers import StringTransportWithDisconnection
10 from twisted.internet.error import ConnectionDone
11
12 from twisted.web.resource import Resource
13 from twisted.web.server import Site
14 from twisted.web.proxy import ReverseProxyResource, ProxyClientFactory
15 from twisted.web.proxy import ProxyClient, ProxyRequest, ReverseProxyRequest
16
17
18
19 class FakeReactor(object):
20 """
21 A fake reactor to be used in tests.
22
23 @ivar connect: a list that keeps track of connection attempts (ie, calls
24 to C{connectTCP}).
25 @type connect: C{list}
26 """
27
28 def __init__(self):
29 """
30 Initialize the C{connect} list.
31 """
32 self.connect = []
33
34
35 def connectTCP(self, host, port, factory):
36 """
37 Fake L{reactor.connectTCP}, that does nothing but log the call.
38 """
39 self.connect.append([host, port, factory])
40
41
42
43 class ReverseProxyResourceTestCase(TestCase):
44 """
45 Tests for L{ReverseProxyResource}.
46 """
47
48 def _testRender(self, uri, expectedURI):
49 """
50 Check that a request pointing at C{uri} produce a new proxy connection,
51 with the path of this request pointing at C{expectedURI}.
52 """
53 root = Resource()
54 reactor = FakeReactor()
55 resource = ReverseProxyResource("127.0.0.1", 1234, "/path", reactor)
56 root.putChild('index', resource)
57 site = Site(root)
58
59 transport = StringTransportWithDisconnection()
60 channel = site.buildProtocol(None)
61 channel.makeConnection(transport)
62 # Clear the timeout if the tests failed
63 self.addCleanup(channel.connectionLost, None)
64
65 channel.dataReceived("GET %s HTTP/1.1\r\nAccept: text/html\r\n\r\n" %
66 (uri,))
67
68 # Check that one connection has been created, to the good host/port
69 self.assertEquals(len(reactor.connect), 1)
70 self.assertEquals(reactor.connect[0][0], "127.0.0.1")
71 self.assertEquals(reactor.connect[0][1], 1234)
72
73 # Check the factory passed to the connect, and its given path
74 factory = reactor.connect[0][2]
75 self.assertIsInstance(factory, ProxyClientFactory)
76 self.assertEquals(factory.rest, expectedURI)
77 self.assertEquals(factory.headers["host"], "127.0.0.1:1234")
78
79
80 def test_render(self):
81 """
82 Test that L{ReverseProxyResource.render} initiates a connection to the
83 given server with a L{ProxyClientFactory} as parameter.
84 """
85 return self._testRender("/index", "/path")
86
87
88 def test_renderWithQuery(self):
89 """
90 Test that L{ReverseProxyResource.render} passes query parameters to the
91 created factory.
92 """
93 return self._testRender("/index?foo=bar", "/path?foo=bar")
94
95
96 def test_getChild(self):
97 """
98 The L{ReverseProxyResource.getChild} method should return a resource
99 instance with the same class as the originating resource, forward port
100 and host values, and update the path value with the value passed.
101 """
102 resource = ReverseProxyResource("127.0.0.1", 1234, "/path")
103 child = resource.getChild('foo', None)
104 # The child should keep the same class
105 self.assertIsInstance(child, ReverseProxyResource)
106 self.assertEquals(child.path, "/path/foo")
107 self.assertEquals(child.port, 1234)
108 self.assertEquals(child.host, "127.0.0.1")
109
110
111 def test_getChildWithSpecial(self):
112 """
113 The L{ReverseProxyResource} return by C{getChild} has a path which has
114 already been quoted.
115 """
116 resource = ReverseProxyResource("127.0.0.1", 1234, "/path")
117 child = resource.getChild(' /%', None)
118 self.assertEqual(child.path, "/path/%20%2F%25")
119
120
121
122 class DummyParent(object):
123 """
124 A dummy parent request that holds a channel and its transport.
125
126 @ivar channel: the request channel.
127 @ivar transport: the transport of the channel.
128 """
129
130 def __init__(self, channel):
131 """
132 Hold a reference to the channel and its transport.
133 """
134 self.channel = channel
135 self.transport = channel.transport
136
137
138
139 class DummyChannel(object):
140 """
141 A dummy HTTP channel, that does nothing but holds a transport and saves
142 connection lost.
143
144 @ivar transport: the transport used by the client.
145 @ivar lostReason: the reason saved at connection lost.
146 """
147
148 def __init__(self, transport):
149 """
150 Hold a reference to the transport.
151 """
152 self.transport = transport
153 self.lostReason = None
154
155
156 def connectionLost(self, reason):
157 """
158 Keep track of the connection lost reason.
159 """
160 self.lostReason = reason
161
162
163
164 class ProxyClientTestCase(TestCase):
165 """
166 Tests for L{ProxyClient}.
167 """
168
169 def _testDataForward(self, data, method="GET", body=""):
170 """
171 Build a fake proxy connection, and send C{data} over it, checking that
172 it's forwarded to the originating request.
173 """
174 # Connect everything
175 clientTransport = StringTransportWithDisconnection()
176 serverTransport = StringTransportWithDisconnection()
177 channel = DummyChannel(serverTransport)
178 parent = DummyParent(channel)
179 serverTransport.protocol = channel
180
181 client = ProxyClient(method, '/foo', 'HTTP/1.0',
182 {"accept": "text/html"}, body, parent)
183 clientTransport.protocol = client
184 client.makeConnection(clientTransport)
185
186 # Check data sent
187 self.assertEquals(clientTransport.value(),
188 "%s /foo HTTP/1.0\r\n"
189 "connection: close\r\n"
190 "accept: text/html\r\n\r\n%s" % (method, body))
191
192 # Fake an answer
193 client.dataReceived(data)
194
195 # Check that the data has been forwarded
196 self.assertEquals(serverTransport.value(), data)
197
198 clientTransport.loseConnection()
199 self.assertIsInstance(channel.lostReason, ConnectionDone)
200
201
202 def test_forward(self):
203 """
204 When connected to the server, L{ProxyClient} should send the saved
205 request, with modifications of the headers, and then forward the result
206 to the parent request.
207 """
208 return self._testDataForward("200 OK\r\nFoo: bar\r\n\r\nSome data\r\n")
209
210
211 def test_postData(self):
212 """
213 Try to post content in the request, and check that the proxy client
214 forward the body of the request.
215 """
216 return self._testDataForward(
217 "200 OK\r\nFoo: bar\r\n\r\nSome data\r\n", "POST", "Some content")
218
219
220 def test_statusWithMessage(self):
221 """
222 If the response contains a status with a message, it should be
223 forwarded to the parent request with all the information.
224 """
225 return self._testDataForward("404 Not Found\r\n")
226
227
228 def test_headersCleanups(self):
229 """
230 The headers given at initialization should be modified:
231 B{proxy-connection} should be removed if present, and B{connection}
232 should be added.
233 """
234 client = ProxyClient('GET', '/foo', 'HTTP/1.0',
235 {"accept": "text/html", "proxy-connection": "foo"}, '', None)
236 self.assertEquals(client.headers,
237 {"accept": "text/html", "connection": "close"})
238
239
240
241 class ProxyClientFactoryTestCase(TestCase):
242 """
243 Tests for L{ProxyClientFactory}.
244 """
245
246 def test_connectionFailed(self):
247 """
248 Check that L{ProxyClientFactory.clientConnectionFailed} produces
249 a B{501} response to the parent request.
250 """
251 serverTransport = StringTransportWithDisconnection()
252 channel = DummyChannel(serverTransport)
253 parent = DummyParent(channel)
254 serverTransport.protocol = channel
255 factory = ProxyClientFactory('GET', '/foo', 'HTTP/1.0',
256 {"accept": "text/html"}, '', parent)
257
258 factory.clientConnectionFailed(None, None)
259 self.assertEquals(serverTransport.value(),
260 "HTTP/1.0 501 Gateway error\r\n"
261 "Content-Type: text/html\r\n\r\n"
262 "<H1>Could not connect</H1>")
263 self.assertIsInstance(channel.lostReason, ConnectionDone)
264
265
266 def test_buildProtocol(self):
267 """
268 L{ProxyClientFactory.buildProtocol} should produce a L{ProxyClient}
269 with the same values of attributes (with updates on the headers).
270 """
271 factory = ProxyClientFactory('GET', '/foo', 'HTTP/1.0',
272 {"accept": "text/html"}, 'Some data',
273 None)
274 proto = factory.buildProtocol(None)
275 self.assertIsInstance(proto, ProxyClient)
276 self.assertEquals(proto.command, 'GET')
277 self.assertEquals(proto.rest, '/foo')
278 self.assertEquals(proto.data, 'Some data')
279 self.assertEquals(proto.headers,
280 {"accept": "text/html", "connection": "close"})
281
282
283
284 class ProxyRequestTestCase(TestCase):
285 """
286 Tests for L{ProxyRequest}.
287 """
288
289 def _testProcess(self, uri, expectedURI, method="GET", data=""):
290 """
291 Build a request pointing at C{uri}, and check that a proxied request
292 is created, pointing a C{expectedURI}.
293 """
294 transport = StringTransportWithDisconnection()
295 channel = DummyChannel(transport)
296 reactor = FakeReactor()
297 request = ProxyRequest(channel, False, reactor)
298 request.gotLength(len(data))
299 request.handleContentChunk(data)
300 request.requestReceived(method, 'http://example.com%s' % (uri,),
301 'HTTP/1.0')
302
303 self.assertEquals(len(reactor.connect), 1)
304 self.assertEquals(reactor.connect[0][0], "example.com")
305 self.assertEquals(reactor.connect[0][1], 80)
306
307 factory = reactor.connect[0][2]
308 self.assertIsInstance(factory, ProxyClientFactory)
309 self.assertEquals(factory.command, method)
310 self.assertEquals(factory.version, 'HTTP/1.0')
311 self.assertEquals(factory.headers, {'host': 'example.com'})
312 self.assertEquals(factory.data, data)
313 self.assertEquals(factory.rest, expectedURI)
314 self.assertEquals(factory.father, request)
315
316
317 def test_process(self):
318 """
319 L{ProxyRequest.process} should create a connection to the given server,
320 with a L{ProxyClientFactory} as connection factory, with the correct
321 parameters:
322 - forward comment, version and data values
323 - update headers with the B{host} value
324 - remove the host from the URL
325 - pass the request as parent request
326 """
327 return self._testProcess("/foo/bar", "/foo/bar")
328
329
330 def test_processWithoutTrailingSlash(self):
331 """
332 If the incoming request doesn't contain a slash,
333 L{ProxyRequest.process} should add one when instantiating
334 L{ProxyClientFactory}.
335 """
336 return self._testProcess("", "/")
337
338
339 def test_processWithData(self):
340 """
341 L{ProxyRequest.process} should be able to retrieve request body and
342 to forward it.
343 """
344 return self._testProcess(
345 "/foo/bar", "/foo/bar", "POST", "Some content")
346
347
348 def test_processWithPort(self):
349 """
350 Check that L{ProxyRequest.process} correctly parse port in the incoming
351 URL, and create a outgoing connection with this port.
352 """
353 transport = StringTransportWithDisconnection()
354 channel = DummyChannel(transport)
355 reactor = FakeReactor()
356 request = ProxyRequest(channel, False, reactor)
357 request.gotLength(0)
358 request.requestReceived('GET', 'http://example.com:1234/foo/bar',
359 'HTTP/1.0')
360
361 # That should create one connection, with the port parsed from the URL
362 self.assertEquals(len(reactor.connect), 1)
363 self.assertEquals(reactor.connect[0][0], "example.com")
364 self.assertEquals(reactor.connect[0][1], 1234)
365
366
367
368 class DummyFactory(object):
369 """
370 A simple holder for C{host} and C{port} information.
371 """
372
373 def __init__(self, host, port):
374 self.host = host
375 self.port = port
376
377
378
379 class ReverseProxyRequestTestCase(TestCase):
380 """
381 Tests for L{ReverseProxyRequest}.
382 """
383
384 def test_process(self):
385 """
386 L{ReverseProxyRequest.process} should create a connection to its
387 factory host/port, using a L{ProxyClientFactory} instantiated with the
388 correct parameters, and particulary set the B{host} header to the
389 factory host.
390 """
391 transport = StringTransportWithDisconnection()
392 channel = DummyChannel(transport)
393 reactor = FakeReactor()
394 request = ReverseProxyRequest(channel, False, reactor)
395 request.factory = DummyFactory("example.com", 1234)
396 request.gotLength(0)
397 request.requestReceived('GET', '/foo/bar', 'HTTP/1.0')
398
399 # Check that one connection has been created, to the good host/port
400 self.assertEquals(len(reactor.connect), 1)
401 self.assertEquals(reactor.connect[0][0], "example.com")
402 self.assertEquals(reactor.connect[0][1], 1234)
403
404 # Check the factory passed to the connect, and its headers
405 factory = reactor.connect[0][2]
406 self.assertIsInstance(factory, ProxyClientFactory)
407 self.assertEquals(factory.headers, {'host': 'example.com'})
OLDNEW
« no previous file with comments | « third_party/twisted_8_1/twisted/web/test/test_mvc.py ('k') | third_party/twisted_8_1/twisted/web/test/test_soap.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698