Ϫf;dZddlZddlZddlZddlmZddlmZmZm Z m Z ddl m Z ddl mZmZmZddlmZddlmZmZmZmZmZmZdd lmZmZdd lmZdd lm Z m!Z!d Z"d Z#dZ$dZ%dZ&dZ'dZ(dZ)dZ*GddejVZ,GddZ-Gdde-ej\Z/Gdde-ej\Z0Gddej\Z1Gdd ej\Z2d!Z3y)"z! Tests for L{twisted.web.twcgi}. N)BytesIO)addresserror interfacesreactor)ConnectionLost)failurelogutil)unittest)clienthttp http_headersresourceservertwcgi)INTERNAL_SERVER_ERROR NOT_FOUND)_render) DummyChannel DummyRequestz2print("Header: OK") print("") print("cgi output") zJprint("Header: spam") print("Header: eggs") print("") print("cgi output") z+print("XYZ") print("") print("cgi output") zPprint("Server: monkeys") print("Date: last year") print("") print("cgi output") a&# This is an example of a correctly-written CGI script which reads a body # from stdin, which only reads env['CONTENT_LENGTH'] bytes. import os, sys body_length = int(os.environ.get('CONTENT_LENGTH',0)) indata = sys.stdin.read(body_length) print("Header: OK") print("") print("readinput ok") a+# This is an example of the typical (incorrect) CGI script which expects # the server to close stdin when the body of the request is complete. # A correct CGI should only read env['CONTENT_LENGTH'] bytes. import sys indata = sys.stdin.read() print("Header: OK") print("") print("readallinput ok") zMprint("content-type: text/cgi-duplicate-test") print("") print("cgi output") zimport json import os print("") print("") vals = {x:y for x,y in os.environ.items() if x.startswith("HTTP_")} print(json.dumps(vals)) z]import os param = str(os.environ['QUERY_STRING']) print("Header: OK") print("") print(param) c$eZdZejZy) PythonScriptN)__name__ __module__ __qualname__sys executablefilter;/usr/lib/python3/dist-packages/twisted/web/test/test_cgi.pyrrbs ^^Fr!rceZdZdZdZdZy)_StartServerAndTearDownMixinc<tj}tjt|}|j dt |tj|}tjd||_ |jjjS)Nscgir)rResourcer sibpath__file__putChildrrSiter listenTCPpgetHostport)selfcgirootcgipathsites r" startServerz(_StartServerAndTearDownMixin.startServergsl  ",,x- fl734{{4 ""1d+vv~~$$$r!cRt|ddr|jjSy)Nr,)getattrr, stopListening)r/s r"tearDownz%_StartServerAndTearDownMixin.tearDownos& 4d #66'') ) $r!ctjj|j}t |d5}|j |ddd|S#1swY|SxYw)Nwt)ospathabspathmktempopenwrite)r/source cgiFilenamecgiFiles r"writeCGIz%_StartServerAndTearDownMixin.writeCGIssNggoodkkm4 +t $ " MM& ! " "s AA N)rrrr4r8rDr r!r"r$r$fs%*r!r$ceZdZdZej j esdZdZ dZ dZ dZ dZ dZd Zd Zd e_d Zd Zd e_dZdZd e_dZdZy)CGITestsz, Tests for L{twcgi.FilteredScript}. z5CGI tests require a functional reactor.spawnProcess()cF|jt}|j|}d|fz}|jd}t j t jd|}|jtj|j|j|S)Nhttp://localhost:%d/cgiasciiGET) rD DUMMY_CGIr4encoder Agentrrequest addCallbackreadBody _testCGI_1)r/rBportnumurlds r"test_CGIzCGITests.test_CGIszmmI. "";/'7*4jj! LL ! ) )&# 6 foo& doo&r!ch|j|dtjjdzy)Ns cgi outputrI) assertEqualr;lineseprL)r/ress r"rQzCGITests._testCGI_1s& mbjj.?.?.HHIr!c.jt}j|}d|fz}|jd}t j t }|jd|}|jtfd}|j||S)zc If the CGI script emits a I{Server} or I{Date} header, these are ignored. rHrIrJcjd|jjdjd|jjdy)Nmonkeysrz last yeardate) assertNotInheaders getRawHeadersresponser/s r" checkResponsez;CGITests.test_protectedServerAndDate..checkResponsesE   Y(8(8(F(Fx(P Q   [(*:*:*H*H*P Qr!) rDSPECIAL_HEADER_CGIr4rLr rMrrNrO discardBodyr/rBrRrSagentrTrcs` r"test_protectedServerAndDatez$CGITests.test_protectedServerAndDates mm$67 "";/'7*4jj! W% MM&# & k" R m$r!c.jt}j|}d|fz}|jd}t j t }|jd|}|jtfd}|j||S)z If the CGI script emits a I{content-type} header, make sure that the server doesn't add an additional (duplicate) one, as per ticket 4786. rHrIrJc`j|jjddg|S)Nz content-typeztext/cgi-duplicate-testrWr_r`ras r"rczBCGITests.test_noDuplicateContentTypeHeaders..checkResponses2     ..~>*+ Or!) rD$NO_DUPLICATE_CONTENT_TYPE_HEADER_CGIr4rLr rMrrNrOrerfs` r""test_noDuplicateContentTypeHeadersz+CGITests.test_noDuplicateContentTypeHeaderss mm$HI "";/'7*4jj! W% MM&# & k"  m$r!czjt}j|}d|fz}|jd}t j t }tjdgdgd}|jd||}fd}|jtj|j||S) zV The CGI script is never called with the Proxy header passed through. rHrIsfoosbar)sProxysX-Innocent-HeaderrJ)r_ctj|jd}jt |j hdy)NrI> HTTP_HOSTHTTP_CONNECTIONHTTP_X_INNOCENT_HEADER)jsonloadsdecoderWsetkeys)rbr_r/s r"rcz7CGITests.test_noProxyPassthrough..checkResponses9jj!9:G   GLLN#J r!) rDHEADER_OUTPUT_CGIr4rLr rMrrHeadersrNrOrP)r/rBrRrSrgr_rTrcs` r"test_noProxyPassthroughz CGITests.test_noProxyPassthroughsmm$56 "";/'7*4jj! W%&&xx @  MM&#wM 7  foo& m$r!c.jt}j|}d|fz}|jd}t j t }|jd|}|jtfd}|j||S)zp If a CGI script emits two instances of the same header, both are sent in the response. rHrIrJc`j|jjdddgy)Nheaderspameggsrkras r"rcz7CGITests.test_duplicateHeaderCGI..checkResponses*   X--;;HEPVGW Xr!) rDDUAL_HEADER_CGIr4rLr rMrrNrOrerfs` r"test_duplicateHeaderCGIz CGITests.test_duplicateHeaderCGIs mmO4 "";/'7*4jj! W% MM&# & k" Y m$r!cjt}j|}d|fz}|jd}t j t }|jd|}|jtgfd}tj|jtj|fd}|j||S)zF Check for the error message in the duplicated header rHrIrJcNjtj|yN)appendr textFromEventDict) eventDictloggedMessagess r" addMessagez4CGITests.test_malformedHeaderCGI..addMessages  ! !#"7"7 "B Cr!cBjdtdzy)Nzignoring malformed CGI header: sXYZ)assertInrepr)ignoredrr/s r"rcz7CGITests.test_malformedHeaderCGI..checkResponses MM1DL@. r!)rDBROKEN_HEADER_CGIr4rLr rMrrNrOrer addObserver addCleanupremoveObserver) r/rBrRrSrgrTrrcrs ` @r"test_malformedHeaderCGIz CGITests.test_malformedHeaderCGIsmm$56 "";/'7*4jj! W% MM&# & k" D  # **J7  m$r!ctjj|j}t |d5}|j t ddd|j|}tjt}d|fz}|jd}|jd|}|jtj|j|j|S#1swYxYw)Nr:rHrIrJ)r;r<r=r>r?r@ READINPUT_CGIr4r rMrrLrNrOrP_test_ReadEmptyInput_1r/rBrCrRrgrSrTs r"test_ReadEmptyInputzCGITests.test_ReadEmptyInput sggoodkkm4 +t $ ) MM- ( )"";/ W%'7*4jj! MM&# & foo& d112 ) )s C''C0cpdtj}|jd}|j||yNz readinput okrIr;rXrLrWr/rYexpecteds r"rzCGITests._test_ReadEmptyInput_10!"**.??7+ h'r!c "tjj|j}t |d5}|j t ddd|j|}tjt}d|fz}|jd}|j|dtjtd}|jtj |j|j"|S#1swYxYwNr:rHrIsPOSTsHere is your stdin)urimethod bodyProducer)r;r<r=r>r?r@rr4r rMrrLrNFileBodyProducerrrOrP_test_ReadInput_1rs r"test_ReadInputzCGITests.test_ReadInputsggoodkkm4 +t $ ) MM- ( )"";/ W%'7*4jj! MM009N1OP   foo& d,,- ) )s DDcpdtj}|jd}|j||yrrrs r"rzCGITests._test_ReadInput_12rr!c tjj|j}t |d5}|j t ddd|j|}d|fz}|jd}tjtj|dtjtd}|jtj |j|j"|S#1swYxYwr)r;r<r=r>r?r@READALLINPUT_CGIr4rLr rMrrNrrrOrP_test_ReadAllInput_1)r/rBrCrRrSrTs r"test_ReadAllInputzCGITests.test_ReadAllInput7sggoodkkm4 +t $ , MM* + ,"";/'7*4jj! LL ! ) )009N1OP *  foo& d//0 , ,s DD cpdtj}|jd}|j||y)Nzreadallinput okrIrrs r"rzCGITests._test_ReadAllInput_1Js0$RZZL1??7+ h'r!cGdd}|}tddg}tjddd|_t j d| }t |||j|jy ) zw L{twcgi.FilteredScript.runProcess} uses the reactor passed as an argument to the constructor. ceZdZdZdZdZy)5CGITests.test_useReactorArgument..FakeReactorzR A fake reactor recording whether spawnProcess is called. Fcd|_y)z Set the C{called} flag to C{True} if C{spawnProcess} is called. @param args: Positional arguments. @param kwargs: Keyword arguments. TN)called)r/argskwargss r" spawnProcesszBCGITests.test_useReactorArgument..FakeReactor.spawnProcess\s # r!N)rrr__doc__rrr r!r" FakeReactorrUs F #r!rabTCP 127.0.0.190z dummy-filerN) rr IPv4Addressr rFilteredScriptr assertTruer)r/r fakeReactorrNrs r"test_useReactorArgumentz CGITests.test_useReactorArgumentOsg  # # "m Sz* ,,UKG'' kJ'"  **+r!N)rrrrrIReactorProcess providedByrskiprUrQrhrmrzrrrtimeoutrrrrrrr r!r"rFrFzs  % % 0 0 9F J*08(8 #$( $N( "!"( ,r!rFc"eZdZdZdZdZdZy)CGIScriptTestsz' Tests for L{twcgi.CGIScript}. c(|jt}|j|}d|fz}tjt }|j d|}|jtj|j|j|S)zk If the CGI script is passed URL parameters, do not fall over, as per ticket 9887. s"http://localhost:%d/cgi?param=1234rJ) rDURL_PARAMETER_CGIr4r rMrrNrOrP_test_urlParameters_1)r/rBrRrSrgrTs r"test_urlParametersz!CGIScriptTests.test_urlParameterssst mm$56 "";/3wj@ W% MM&# & foo& d001r!cpdtj}|jd}|j||y)Nz param=1234rIrrs r"rz$CGIScriptTests._test_urlParameters_1s0 |,??7+ h'r!cGdd}|}tj|j|}tddg}t j ddd|_t|||j|jd d y ) zt L{twcgi.CGIScript.render} sets the process environment I{PATH_INFO} from the request path. ceZdZdZdZy)1CGIScriptTests.test_pathInfo..FakeReactorzZ A fake reactor recording the environment passed to spawnProcess. c||_y)a9 Store the C{env} L{dict} to an instance attribute. @param process: Ignored @param filename: Ignored @param args: Ignored @param env: The environment L{dict} which will be stored @param wdir: Ignored N) process_env)r/processfilenamerenvwdirs r"rz>CGIScriptTests.test_pathInfo..FakeReactor.spawnProcesss $' r!N)rrrrrr r!r"rrs   'r!rrrrrrr PATH_INFOz/a/bN) r CGIScriptr>rrrr rrWr)r/r_reactorrrNs r" test_pathInfozCGIScriptTests.test_pathInfost  ' '"=??4;;=(CSz* ,,UKG'" --k:FCr!N)rrrrrrrr r!r"rrns ( Dr!rceZdZdZdZdZy)CGIDirectoryTestsz* Tests for L{twcgi.CGIDirectory}. ctjj}tdgt |}fd}|j ||S)zc L{twcgi.CGIDirectory.render} sets the HTTP response code to I{NOT FOUND}. cFjjtyrrW responseCoderrrNr/s r" cbRenderedz1CGIDirectoryTests.test_render..cbRendered   W119 =r!)r CGIDirectoryr>rrrO)r/rrTrrNs` @r" test_renderzCGIDirectoryTests.test_rendersK %%dkkm4t$ Hg & > j!r!cj}tj|tj|}t dg|j d}t|}fd}|j||S)a L{twcgi.CGIDirectory.getChild} returns a resource which renders an response with the HTTP I{NOT FOUND} status code if the indicated child does not exist as an entry in the directory used to initialized the L{twcgi.CGIDirectory}. foocFjjtyrrrs r"rz8CGIDirectoryTests.test_notFoundChild..cbRenderedrr!) r>r;makedirsrrrgetChildrrO)r/r<rchildrTrrNs` @r"test_notFoundChildz$CGIDirectoryTests.test_notFoundChildsp{{} D%%d+w'!!!%1 E7 # > j!r!N)rrrrrrr r!r"rrs r!rceZdZdZdZdZy)CGIProcessProtocolTestsz0 Tests for L{twcgi.CGIProcessProtocol}. ctdg}tj|}|jt j t j|j|jty)z If the process communicating with L{CGIProcessProtocol} ends before finishing writing out headers, the response has I{INTERNAL SERVER ERROR} as its status code. rN) rrCGIProcessProtocol processEndedr FailurerProcessTerminatedrWrr)r/rNprotocols r"test_prematureEndOfHeadersz2CGIProcessProtocolTests.test_prematureEndOfHeaderssW t$++G4gooe.E.E.GHI --/DEr!c4t}tj|d}tj|}|j t jtd|jt jtjy)zg Ensure that the CGI process ends cleanly when the request connection is lost. TzConnection doneN) rrRequestrrconnectionLostr rrrrr)r/rTrNrs r"test_connectionLostz+CGIProcessProtocolTests.test_connectionLostsh N,,q$'++G4w~>O/PQRgooe.E.E.GHIr!N)rrrrrrr r!r"rrs F Jr!rcRtjjfdS)zn Discard the body of a HTTP response. @param response: The response. @return: The response. cSrr )_rbs r"zdiscardBody..s8r!)r rPrO)rbs`r"reres  ??8 $ 0 01C DDr!)4rrsr;riortwisted.internetrrrrtwisted.internet.errorrtwisted.pythonr r r twisted.trialr twisted.webr rrrrrtwisted.web.httprrtwisted.web.test._utilrtwisted.web.test.requesthelperrrrKrrrdrrrlrxrrrr$TestCaserFrrrrer r!r"rs @@1--"KK=*E      ($ 5''(q,+X->->q,h5D183D3D5Dp&))&RJh//J8Er!