ϪfLNdZddlmZmZddlmZddlmZmZm Z m Z m Z ddl m Z ddlmZddlmZGdd eZGd d ZGd d eZGddeZGddeZGddZGddeZy)z Test for L{twisted.web.proxy}. ) MemoryReactor StringTransportWithDisconnection)TestCase) ProxyClientProxyClientFactory ProxyRequestReverseProxyRequestReverseProxyResource)Resource)Site DummyRequestc4eZdZdZdZdZdZdZdZdZ y) ReverseProxyResourceTestsz, Tests for L{ReverseProxyResource}. cRt}t}tddd|}|jd|t |}t }|j d}|j||j|jd|jd|zdz|j\\} } } } } |j| d|j| d|j| t|j| j||j| j dd y) z Check that a request pointing at C{uri} produce a new proxy connection, with the path of this request pointing at C{expectedURI}. 127.0.0.1/pathsindexNsGET s HTTP/1.1 Accept: text/html hosts127.0.0.1:1234)r rr putChildr r buildProtocolmakeConnection addCleanupconnectionLost dataReceived tcpClients assertEqualassertIsInstancerrestheaders)selfuri expectedURIrootreactorresourcesite transportchannelhostportfactory_timeout _bind_addrs =/usr/lib/python3/dist-packages/twisted/web/test/test_proxy.py _testRenderz%ReverseProxyResourceTests._testRenders z/' T8WM h)Dz46 $$T*y) ..5Ws]-VVW8?8J8J5 4$gx {+ t$ g'9: {3 13DEc&|jddS)z Test that L{ReverseProxyResource.render} initiates a connection to the given server with a L{ProxyClientFactory} as parameter. s/indexrr0r!s r/ test_renderz%ReverseProxyResourceTests.test_render8s  844r1c&|jddS)z Test that L{ReverseProxyResource.render} will instantiate a child resource that will initiate a connection to the given server requesting the apropiate url subpath. s /index/page1s /path/page1r3r4s r/test_render_subpagez-ReverseProxyResourceTests.test_render_subpage?s @@r1c&|jddS)zr Test that L{ReverseProxyResource.render} passes query parameters to the created factory. s/index?foo=bars /path?foo=barr3r4s r/test_renderWithQueryz.ReverseProxyResourceTests.test_renderWithQueryGs  13CDDr1cxt}tddd|}|jdd}|j|t|j |j d|j |j d|j |jd|j|j|jy)a The L{ReverseProxyResource.getChild} method should return a resource instance with the same class as the originating resource, forward port, host, and reactor values, and update the path value with the value passed. rrrfooNs /path/foo) rr getChildrrpathr+r*assertIdenticalr%)r!r%r&childs r/ test_getChildz'ReverseProxyResourceTests.test_getChildNs /' T8WM!!&$/ e%9: \2 T* [1 U]]H,<,<=r1cztddd}|jdd}|j|jdy)zu The L{ReverseProxyResource} return by C{getChild} has a path which has already been quoted. rrrs /%Ns/path/%20%2F%25)r r<rr=)r!r&r?s r/test_getChildWithSpecialz2ReverseProxyResourceTests.test_getChildWithSpecial_s9 ( T8D!!&$/ %78r1N) __name__ __module__ __qualname____doc__r0r5r7r9r@rBr1r/rrs(F:5AE>"9r1rc(eZdZdZdZdZdZdZy) DummyChannelz A dummy HTTP channel, that does nothing but holds a transport and saves connection lost. @ivar transport: the transport used by the client. @ivar lostReason: the reason saved at connection lost. c ||_d|_y)z4 Hold a reference to the transport. N)r( lostReason)r!r(s r/__init__zDummyChannel.__init__rs#r1c||_y)z; Keep track of the connection lost reason. N)rK)r!reasons r/rzDummyChannel.connectionLostys !r1c6|jjS)z: Get peer information from the transport. )r(getPeerr4s r/rPzDummyChannel.getPeer~~%%''r1c6|jjS)z: Get host information from the transport. )r(getHostr4s r/rSzDummyChannel.getHostrQr1N)rCrDrErFrLrrPrSrGr1r/rIrIis! ( (r1rIczeZdZdZdZdZddZdZdZdZ d Z dd Z d Z d Z d ZdZdZdZdZdZy)ProxyClientTestsz# Tests for L{ProxyClient}. c|jd\}}|jd}|jd}|td|D|fS)aC Parse the headers out of some web content. @param content: Bytes received from a web server. @return: A tuple of (requestLine, headers, body). C{headers} is a dict of headers, C{requestLine} is the first line (e.g. "POST /foo ...") and C{body} is whatever is left. s  rc3>K|]}|jdyw): N)split).0headers r/ z4ProxyClientTests._parseOutHeaders..s!L&&,,u"5!Ls)rZpopdict)r!contentr body requestLines r/_parseOutHeadersz!ProxyClientTests._parseOutHeaderssI k2 --(kk!n T!LG!LLdSSr1ct|S)z Make a dummy request object for the URL path. @param path: A URL path, beginning with a slash. @return: A L{DummyRequest}. r )r!r=s r/ makeRequestzProxyClientTests.makeRequestsD!!r1NcL|ddi}d|jz}t||d|||S)a Make a L{ProxyClient} object used for testing. @param request: The request to use. @param method: The HTTP method to use, GET by default. @param headers: The HTTP headers to use expressed as a dict. If not provided, defaults to {'accept': 'text/html'}. @param requestBody: The body of the request. Defaults to the empty string. @return: A L{ProxyClient} accept text/html/HTTP/1.0)postpathr)r!requestmethodr requestBodyr=s r/makeProxyClientz ProxyClientTests.makeProxyClients8 ? ,/Gg&&&64g{GTTr1cJt}||_|j||S)z Connect a proxy client to a L{StringTransportWithDisconnection}. @param proxyClient: A L{ProxyClient}. @return: The L{StringTransportWithDisconnection}. )rprotocolr)r! proxyClientclientTransports r/ connectProxyzProxyClientTests.connectProxys(;<#. ""?3r1c|j||jj}|j|\}}}|j |||j |||S)a` Assert that C{proxyClient} sends C{headers} when it connects. @param proxyClient: A L{ProxyClient}. @param requestLine: The request line we expect to be sent. @param headers: A dict of headers we expect to be sent. @return: If the assertion is successful, return the request body as bytes. )rtr(valuercr)r!rrrbr requestContent receivedLinereceivedHeadersras r/assertForwardsHeadersz&ProxyClientTests.assertForwardsHeaderssb +&$..446.2.C.CN.S+ ot {3 '2 r1cdt|jdzdz|zg}|D]#\}}|D]}|j|dz|z%|jd|gdj |S)Ns HTTP/1.0 ascii rYr1rW)strencodeappendextendjoin) r!codemessager ralinesr\valuesrvs r/makeResponseBytesz"ProxyClientTests.makeResponseBytessD 0 0 99D@7JK% 5NFF 5 Ve^e34 5 5  c4[!||E""r1c~|j|j||j|j|t|jj }|j |dd}|j |j|||jdj|j|y)aK Assert that C{request} has forwarded a response from the server. @param request: A L{DummyRequest}. @param code: The expected HTTP response code. @param message: The expected HTTP message. @param headers: The expected HTTP headers. @param body: The expected response body. Nr1) r responseCoderesponseMessagelistresponseHeadersgetAllRawHeaderssortrwritten)r!rlrrr raryexpectedHeaderss r/assertForwardsResponsez'ProxyClientTests.assertForwardsResponses --t4 00':w66GGIJ!!* /: '//2D9r1c|jd}|j||ddi|} |j| |dzddd} |j| || j |j |||||j ||||||r| jj|j| jj|j|jdy) z Build a fake proxy connection, and send C{data} over it, checking that it's forwarded to the originating request. r;rgrhs /foo HTTP/1.0close) connectionrgN) rerorzrrrrr(loseConnection assertFalse connectedfinished) r!rrr rarmrnrrlclient receivedBodys r/_testDataForwardz!ProxyClientTests._testDataForwards""6*%% Vi6  11  & &$ > {3 D224'4PQ ##GT7GTJ     + + - ))334 ))1-r1c4|jdddddgfgdS)z When connected to the server, L{ProxyClient} should send the saved request, with modifications of the headers, and then forward the result to the parent request. OKFoobarsbaz Some data rr4s r/ test_forwardzProxyClientTests.test_forwards. $$ &66"2346F  r1c6|jddddgfgdddS)z~ Try to post content in the request, and check that the proxy client forward the body of the request. rrrrrPOST Some contentrr4s r/ test_postDatazProxyClientTests.test_postData's/ $$ &6(+,.>  r1c*|jddgdS)z If the response contains a status with a message, it should be forwarded to the parent request with all the information. is Not Foundr1rr4s r/test_statusWithMessagez'ProxyClientTests.test_statusWithMessage0s $$S,C@@r1c xd}|jdddtt|jdgfg|S)z If the response contains a I{Content-Length} header, the inbound request object should still only have C{finish} called on it once. foo bar bazrrContent-Lengthr|rr~lenrr!datas r/test_contentLengthz#ProxyClientTests.test_contentLength7sE $$ +c#d)n.C.CG.L-MNOQU  r1c |d}|jdddtt|jdgfg|dS)z If the response contains a I{Content-Length} header, the outgoing connection is closed when all response body data has been received. rrrrr|F)rrrs r/test_losesConnectionz%ProxyClientTests.test_losesConnectionAsN $$  #c$i."7"7"@!A B C  %  r1chtdddddddd}|j|jdd d y) z The headers given at initialization should be modified: B{proxy-connection} should be removed if present, and B{connection} should be added. GET/foorjrhr;)rgsproxy-connectionr1Nrrgr)rrr )r!rs r/test_headersCleanupsz%ProxyClientTests.test_headersCleanupsOsC    $6 B      NN XN r1cdddd}|j}d|d<|d=tddd |d d }|j|d |y ) z The proxy doesn't really know what to do with keepalive things from the remote server, so we stomp over any keepalive header we get from the client. rhs300 keep-alive)rgrrrrrrrjr1NsGET /foo HTTP/1.0)copyrrz)r!r rrs r/test_keepaliveNotForwardedz+ProxyClientTests.test_keepaliveNotForwardedasZ$!(  ",,.)1 & M *VWk7CN ""6+?Qr1c |jd}|jjddg|jjddg|jjddg|j|dd i }|j |d gd gd gd}|j |j dd|jd|j|ddt|jdy)z L{server.Request} within the proxy sets certain response headers by default. When we get these headers back from the remote server, the defaults are overridden rather than simply appended. r;sserversold-barsdatesold-bazs content-typesold/quxrgrh)r rs 2010-01-01sapplication/x-baz)sServersDate Content-Typerrr1N) rer setRawHeadersrortrritemsrr)r!rlrr s r/test_defaultHeadersOverriddenz.ProxyClientTests.test_defaultHeadersOverriddenrs ""6*--i*F--g |D--o |L%%g <7P%Q &!x#_23  D223w}}PSTU ##GS%gmmo9NPSTr1)rNr1)rr1T)rCrDrErFrcrerortrzrrrrrrrrrrrrGr1r/rUrUsh T"U" "#:2*.X  A    $R"Ur1rUceZdZdZdZdZy)ProxyClientFactoryTestsz* Tests for L{ProxyClientFactory}. ctdg}tdddddid|}|jdd|j|jd |j|j d |jt |jjd dgfg|jd j|jd |j|jdy)z Check that L{ProxyClientFactory.clientConnectionFailed} produces a B{501} response to the parent request. r;rrrjrgrhNis Gateway errorrr1s

Could not connect

r) rrclientConnectionFailedrrrrrrrrr)r!rlr,s r/test_connectionFailedz-ProxyClientFactoryTests.test_connectionFaileds x($ G[9l*CR  &&tT2 --s3 002BC  ((99; < ~ . /  '//24QR ))1-r1c\tdddddidd}|jd}|j|t|j |j d|j |j d|j |jd|j |jddd y) z L{ProxyClientFactory.buildProtocol} should produce a L{ProxyClient} with the same values of attributes (with updates on the headers). rrrjrgrhs Some dataNrr) rrrrrcommandrrr )r!r,protos r/test_buildProtocolz*ProxyClientFactoryTests.test_buildProtocols % G[9l*C\SW %%d+ e[1 / W- \2  MM|HM r1N)rCrDrErFrrrGr1r/rrs.( r1rc0eZdZdZddZdZdZdZdZy) ProxyRequestTestsz$ Tests for L{ProxyRequest}. cTt}t|}t}t|d|}|j t ||j ||j|d|zd|jt |jd|j|jddd|j|jddd|jdd} |j| t|j| j||j| jd|j| jd d i|j| j||j| j ||j| j"|y ) z Build a request pointing at C{uri}, and check that a proxied request is created, pointing a C{expectedURI}. Fshttp://example.comrjrr example.comPr example.comN)rrIrr gotLengthrhandleContentChunkrequestReceivedrrrrrversionr rrfather) r!r"r#rmrr(r)r%rlr,s r/ _testProcesszProxyRequestTests._testProcesssa 56 y)/ww7#d)$""4((=(C[Q W//0!4 ++A.q1=A ++A.q126$$Q'* g'9: &1 +6 7N*CD t, {3 1r1c&|jddS)a L{ProxyRequest.process} should create a connection to the given server, with a L{ProxyClientFactory} as connection factory, with the correct parameters: - forward comment, version and data values - update headers with the B{host} value - remove the host from the URL - pass the request as parent request /foo/barrr4s r/ test_processzProxyRequestTests.test_processs  k::r1c&|jddS)z If the incoming request doesn't contain a slash, L{ProxyRequest.process} should add one when instantiating L{ProxyClientFactory}. r1rirr4s r/ test_processWithoutTrailingSlashz2ProxyRequestTests.test_processWithoutTrailingSlashs   d++r1c*|jddddS)zl L{ProxyRequest.process} should be able to retrieve request body and to forward it. rrrrr4s r/test_processWithDataz&ProxyRequestTests.test_processWithDatas   k7OTTr1cvt}t|}t}t|d|}|j d|j ddd|j t|jd|j |jddd|j |jdddy ) z Check that L{ProxyRequest.process} correctly parse port in the incoming URL, and create an outgoing connection with this port. Frrshttp://example.com:1234/foo/barrjrrrN) rrIrrrrrrr)r!r(r)r%rls r/test_processWithPortz&ProxyRequestTests.test_processWithPorts 56 y)/ww7!(JKX W//0!4 ++A.q1=A ++A.q148r1N)rr1) rCrDrErFrrrrrrGr1r/rrs!24 ;,U9r1rceZdZdZdZy) DummyFactoryz> A simple holder for C{host} and C{port} information. c ||_||_y)N)r*r+)r!r*r+s r/rLzDummyFactory.__init__s  r1N)rCrDrErFrLrGr1r/rrs r1rceZdZdZdZy)ReverseProxyRequestTestsz+ Tests for L{ReverseProxyRequest}. c$t}t|}t}t|d|}t dd|_|j d|jddd|jt|jd|j|jddd|j|jddd|jdd }|j|t|j|jd d iy ) a L{ReverseProxyRequest.process} should create a connection to its factory host/port, using a L{ProxyClientFactory} instantiated with the correct parameters, and particularly set the B{host} header to the factory host. FrrrrrrjrrrrN)rrIrr rr,rrrrrrrr )r!r(r)r%rlr,s r/rz%ReverseProxyRequestTests.test_process s56 y)/%gug>&}d;! [A W//0!4 ++A.q1=A ++A.q148$$Q'* g'9: 7N*CDr1N)rCrDrErFrrGr1r/rrs Er1rN)rFtwisted.internet.testingrrtwisted.trial.unittestrtwisted.web.proxyrrrr r twisted.web.resourcer twisted.web.serverr twisted.web.test.test_webrrrIrUrrrrrGr1r/rsU+*#2P9P9f ( (FxUxxUv( h( VI9I9XExEr1