ϪfdZddlZddlZddlmZddlmZddlmZddl m Z ddl m Z ddl mZmZdd lmZdd lmZmZdd lmZmZdd lmZmZdd lmZddlmZddlm Z ddl!m"Z"m#Z#m$Z$m%Z%m&Z&ddl'm(Z(ddl)m*Z*m+Z+m,Z,ddl-m.Z.ddl/m0Z0m1Z1ddl2m3Z3Gdde jhZ5Gdde%jPZ6Gdde%jPZ7Gdde%jPZ8Gdd e jhZ9Gd!d"e jhZ:d#Z;d$ZGd(d)e jhZ?Gd*d+e jhZ@Gd,d-e%jPZAGd.d/e jhZBGd0d1e%jPZCee%jGd2d3ZEGd4d5e jhZFGd6d7e%jPZGGd8d9e jhZHGd:d;e1ZIGd<d=ZJGd>d?eJe jhZKGd@dAeJe jhZLGdBdCe jhZMGdDdEe jhZNGdFdGe jhZOGdHdIe jhZPGdJdKe jhZQGdLdMe(ZRGdNdOe jhZSy)Pz, Tests for various parts of L{twisted.web}. N)BytesIO)List) implementer) verifyObject) interfaces) IPv4Address IPv6Address)Clock)EventLoggingObserverStringTransport)LogLevelglobalLogPublisher)failurereflect) iterbytes)FilePath)unittest)errorhttpiwebresourceserver)Resource) NOT_DONE_YETRequestSite)Data) DummyChannel DummyRequest)assertIsFilesystemTemporaryceZdZdZy) ResourceTestscltj}|jg|jyN)rr assertEqual listEntities)selfrs ;/usr/lib/python3/dist-packages/twisted/web/test/test_web.pytestListEntitieszResourceTests.testListEntities"s'     Q^^-.N)__name__ __module__ __qualname__r+r,r*r#r#!s/r,r#ceZdZdZddZdZy)SimpleResourcez @ivar _contentType: L{None} or a C{str} giving the value of the I{Content-Type} header in the response this resource will render. If it is L{None}, no I{Content-Type} header will be set in the response. NcPtjj|||_yr%)rr__init__ _contentType)r( contentTypes r*r4zSimpleResource.__init__.s""4('r,c|j'|jjd|jgtj|j d|j dfvryy)N content-type MatchingTagr,correct)r5responseHeaders setRawHeadersrCACHEDsetLastModifiedsetETagr(requests r*renderzSimpleResource.render2s`    (  # # 1 1/DDUDUCV W ;;  # #B ' OON +  r,r%)r-r.r/__doc__r4rCr0r,r*r2r2's ( r,r2ceZdZdZdZy)ZeroLengthResourcez@ A resource that always returns a zero-length response. cyNr,r0rAs r*rCzZeroLengthResource.renderDsr,Nr-r.r/rDrCr0r,r*rFrF?s r,rFceZdZdZdZy)NoContentResourcezf A resource that always returns a 204 No Content response without setting Content-Length. cB|jtjyrH)setResponseCoder NO_CONTENTrAs r*rCzNoContentResource.renderNs0r,NrIr0r,r*rKrKHs  r,rKcFeZdZdZdZdZdZdZdZdZ dZ d Z d Z y ) SiteTestz( Unit tests for L{server.Site}. c\|j}|j|j|S)z Create a new session which auto expires at cleanup. @param site: The site on which the session is created. @type site: L{server.Site} @return: A newly created session. @rtype: L{server.Session} ) makeSession addCleanupexpirer(sitesessions r*getAutoExpiringSessionzSiteTest.getAutoExpiringSessionXs'""$ 'r,ct}t}|jd|tj|}|j |j t dg|dy)z L{Site.getResourceFor} returns the C{b""} child of the root resource it is constructed with when processing a request for I{/}. r,zGot the wrong resource.N)r2putChildrrassertIdenticalgetResourceForr)r(sres1sres2rVs r*test_simplestSitezSiteTest.test_simplestSitegsX    sE"{{5!     cU 3 4e=V r,ctjt}|jtj|j y)zC L{server.Request} is the default request factory. )rN)rrr2assertIsrrequestFactoryr(rVs r*test_defaultRequestFactoryz#SiteTest.test_defaultRequestFactoryts-{{N$45 fnnd&9&9:r,ct}tjt|}|j ||j y)zB Can be initialized with a custom requestFactory. )rrbN)objectrrr2rarb)r( customFactoryrVs r*test_constructorRequestFactoryz'SiteTest.test_constructorRequestFactory|s2 {{N$4]S mT%8%89r,ctjt}|jd}|j ||j |j |j |j y)z Returns a C{Channel} whose C{site} and C{requestFactory} attributes are assigned from the C{site} instance. N)rrr2 buildProtocolrarVrb)r(rVchannels r*test_buildProtocolzSiteTest.test_buildProtocolsQ {{>+,$$T* dGLL) d))7+A+ABr,ctjtj}|j |}|j |tj |j |jty)zn L{site.getSession} generates a new C{Session} instance with an uid of type L{bytes}. N) rrrrrXassertIsInstanceSessionuidbytesrUs r*test_makeSessionzSiteTest.test_makeSessionsS {{8,,./--d3 gv~~6 gkk51r,ctjtj}|j |j t jfdd_|j|d|j|}|j|}|j|jd|j|jd|j|jdy)z} L{site.getSession} generates L{Session} objects with distinct UIDs from a secure source of entropy. c|xjdz c_tj|zjdS)Nr charmap)xchrencode)npredictableEntropys r*rzz>SiteTest.test_sessionUIDGeneration..predictableEntropys6  A % *,,-199)D Dr,r_entropys@0101010101010101010101010101010101010101010101010101010101010101s@0202020202020202020202020202020202020202020202020202020202020202N)rrrrr[r{osurandomrvpatchrXr&rpcounter)r(rVabrzs @r*test_sessionUIDGenerationz"SiteTest.test_sessionUIDGenerations {{8,,./ T]]BJJ7 E ! 4%78  ' ' -  ' ' -  -  - q)r,ctjtj}|j |}|j |j }|j||y)zc L{site.getSession} gets a previously generated session, by its unique ID. N)rrrrrX getSessionrpra)r(rVcreatedSessionretrievedSessions r*test_getSessionExistentz SiteTest.test_getSessionExistentsO {{8,,./44T:??>+=+=> n&67r,ctjtj}|j t |j dy)zV L{site.getSession} raises a L{KeyError} if the session is not found. s no-such-uidN)rrrr assertRaisesKeyErrorrrcs r*test_getSessionNonExistentz#SiteTest.test_getSessionNonExistents1{{8,,./ (DOO^Dr,N) r-r.r/rDrXr_rdrhrlrrrrrr0r,r*rPrPSs6   ;: C 2*4 8Er,rPc@eZdZdZdZdZdZdZdZdZ dZ d Z y ) SessionTestsz& Tests for L{server.Session}. cXt|_d|_tjt j |j|_tj|j|j|_ |j|jj|j<y)zo Create a site with one active session using a deterministic, easily controlled clock. suniquereactorN) r clockrprrrrrVrorWsessionsr(s r*setUpzSessionTests.setUpsi W KK 1 1 3TZZH ~~dii: '+|| 488$r,ctjtjt }tj |d}|j |j|jy)z| If no value is passed to L{server.Session.__init__}, the reactor associated with the site is used. r123N) rrrrr ror[_reactorrrUs r*test_defaultReactorz SessionTests.test_defaultReactorsI {{8,,.@..v. W--t||.expireds !KNr,rN)rWnotifyOnExpirerT assertTrue)r(rrs @r*test_notifyOnExpirez SessionTests.test_notifyOnExpiresE g  " ##G,   A'r,c|jjd|jj|j |jj d|jj |jj|jjdz |jj|jj|jjdz |j|j|jj|jjd|j|j|jjy)zt L{server.Session.touch} updates L{server.Session.lastModified} and delays session timeout. r N) rrrWtouchr& lastModifiedrrrrprVrrrs r* test_touchzSessionTests.test_touch"s 1  22A6 ,,. 4<<66:;  4<<66:; dhh 2 23 1 499#5#56r,N) r-r.r/rDrrrrrrrrr0r,r*rrs/ 4= =+$+ (7r,rc,|jdddS)N r )split)wholes r*httpBodyrBs ;;{A &q ))r,c|j}|jddd}|jdD]F}|jj|s#|jdddjcSy)Nrr r :)lowerr startswithstrip)rkeyheadersheaders r* httpHeaderrFsr ))+Ckk+q)!,G--(4 <<> $ $S )<<a(+113 34 r,cd|jddd}t|jdS)Nrr r)rint)rl1s r*httpCoderOs, Wa  #B rxxz!} r,cZeZdZdZdZdZddZdZdZdZ d Z d Z d Z d Z d ZdZy)ConditionalTestszM web.server's handling of conditional requests for cache validation. ct|_|jjd|j|jjdtdtj|j|_|j j |j|j j|j jd|_ tj|_ d|j_d|j_d|j_d|j_|jj%|jy)Nr,swith-content-type image/jpegcyr%r0rkws r*z(ConditionalTests.setUp..dr,cy)Nrr0rs r*rz(ConditionalTests.setUp..err,cy)Npeerr0rs r*rz(ConditionalTests.setUp..frr,cy)Nhostr0rs r*rz(ConditionalTests.setUp..grr,)r2resrcrZrrrV startFactoryrS stopFactoryrjrkrr transportclose disconnectinggetPeergetHostmakeConnectionrs r*rzConditionalTests.setUpYs#%  C, 0.2OPKK +     --.yy..t4 --/4'9$!8!8 ##DNN3r,c:|jjdyr%)rkconnectionLostrs r*tearDownzConditionalTests.tearDownjs ##D)r,Ncb|d|z}nd|z}d|dfD] }|jj|dz"|jj}|j t |t j|j t|d|j t|dd y) a  Given the value C{modifiedSince} for the I{If-Modified-Since} header or the value C{etag} for the I{If-Not-Match} header, verify that a response with a 200 code, a default Content-Type, and the resource as the body is returned. NIf-Modified-Since: sIf-Not-Match: GET / HTTP/1.1r,rr; Content-Types text/html) rk dataReceivedrgetvaluer&rrOKrr)r( modifiedSinceetag validatorlineresults r* _modifiedTestzConditionalTests._modifiedTestms  $.>I)D0I& 37 6D LL % %dWn 5 6((* &)4773 &):6 FO)>q)ABr,ctddtjdzdfD] }|jj|dz"|jj }|j t|tj|j t|d|j t|ddy)a= If a request is made with an I{If-Modified-Since} header value with a timestamp indicating a time after the last modification of the request resource, a 304 response is returned along with an empty response body and no Content-Type header if the application does not set one. rrdr,rrN) rrrkrrrr&r NOT_MODIFIEDrrr(rrs r*test_unmodifiedz ConditionalTests.test_unmodifieds  "T%:%:3%? ?   6D LL % %dWn 5  6 ((* &)4+<+<= &)3/ FO Tests for the HTTP request class, L{server.Request}. c |jttjt j t dy)zG L{server.Request} instances provide L{iweb.IRequest}. TN)rrrIRequestrrrrs r*test_interfacezRequestTests.test_interfaces+  |~t(L M r,cVtjtd}t|y)zY L{server.Request} instances are hashable, thus can be put in a mapping. TN)rrrhashrAs r* test_hashablezRequestTests.test_hashables..6 W r,ctjtd}|jd|j ddd|j |j ddtjtd}|jd|j ddd|j |j ddy) Nr rGET/foo/barHTTP/1.0sbazsbar/baz /foo/bar/)rrr gotLengthrequestReceivedr& childLinkrAs r* testChildLinkzRequestTests.testChildLinks..3! [A **62J?..3! kB **62F;r,ctjtd}|jd|j ddd|j dd|j |jdy) Nr rrrr example.comPshttp://example.com/foo/bar)rrrrrsetHostr& prePathURLrAs r*testPrePathURLSimplez!RequestTests.testPrePathURLSimple s\..3! [A+ ++-/LMr,ct}d|j_tj|d}|j dd|j d|jddd|j|jdy) NQr rrrrrshttp://example.com:81/foo/bar rrportrrrrrr&rr(drBs r*testPrePathURLNonDefaultz%RequestTests.testPrePathURLNonDefaultsm N ..A&+! [A ++-/OPr,ct}d|j_tj|d}|j dd|j d|jddd|j|jdy) Nr rrrrrshttp://example.com:443/foo/barr#r%s r*testPrePathURLSSLPortz"RequestTests.testPrePathURLSSLPortsm N ..A&,! [A ++-/PQr,cDt}tj|_d|j_t j |d}|j dd|jd|jddd|j|jdy) Nr)r rrrrrshttps://example.com/foo/bar rSSLrr$rrrrrr&rr%s r*testPrePathURLSSLPortAndSSLz(RequestTests.testPrePathURLSSLPortAndSSL$s} N"&&(  ..A&,! [A ++-/MNr,cDt}tj|_d|j_t j |d}|j dd|jd|jddd|j|jdy) Nrr rrrrrshttps://example.com:80/foo/barr,r%s r*testPrePathURLHTTPPortAndSSLz)RequestTests.testPrePathURLHTTPPortAndSSL.} N"&&(  ..A&+! [A ++-/PQr,cDt}tj|_d|j_t j |d}|j dd|jd|jddd|j|jdy) Nr"r rrrrrshttps://example.com:81/foo/barr,r%s r*testPrePathURLSSLNonDefaultz(RequestTests.testPrePathURLSSLNonDefault8r1r,ct}d|j_tj|d}|j ddd|j d|jddd|j|jdy) Nr"r sfoo.comrrrrshttps://foo.com:81/foo/barr#r%s r*testPrePathURLSetSSLHostz%RequestTests.testPrePathURLSetSSLHostBso N ..A& B*! [A ++-/LMr,ct}tj|d}|jdd|j d|j ddd|j |jdy ) z L{Request.prePathURL} quotes special characters in the URL segments to preserve the original meaning. r rrrrs /foo%2Fbarrshttp://example.com/foo%2FbarN)rrrrrrr&rr%s r*test_prePathURLQuotingz#RequestTests.test_prePathURLQuotingKsc N..A&+! {C ++-/NOr,ctj|t}t}t j |d}t j tj|_ tjtd}|j||jd|jj j#|j%d|jj j#|j'dt)||d}|d}|j+|j,t|j'|j/d|j1dt)|j3y)z By default, L{Request.processingFailed} does not write out the failure, but give a generic error message, as L{Site.displayTracebacks} is disabled by default. r Oh no!Oh no!Processing Failedr log_failureN)r createWithCleanuprrrrrrrrVrFailure ExceptionprocessingFailedrrwrittenrr assertEqualslenrnvaluegetErrorMessager&flushLoggedErrorsr( logObserverr&rBfaileventfs r*)test_processingFailedNoTracebackByDefaultz6RequestTests.test_processingFailedNoTracebackByDefaultWs& +<r?r@rrrArrrBrCrnrDrEr&rFrGs r* test_processingFailedNoTracebackz-RequestTests.test_processingFailedNoTracebackrs2 +<r?r@rrrArrnrDrBrEr&rCrFrGs r*%test_processingFailedDisplayTracebackz2RequestTests.test_processingFailedDisplayTracebacks +<r?r@rrrArrF UnicodeErrorrnrDr&rCrGs r*3test_processingFailedDisplayTracebackHandlesUnicodez@RequestTests.test_processingFailedDisplayTracebackHandlesUnicodes +<?r,cttjtj}t }tj |d}||_g|_fd}|j||_ |j}jj|j}|j|j|j|||j!|j"|j"y)zn L{Request.getSession} generates a new session when the previous session has expired. r c(||}|_|S)ap Forward to normal session factory, but inject the clock. @param site: The site on which the session is created. @type site: L{server.Site} @param uid: A unique identifier for the session. @type uid: C{bytes} @return: A newly created session. @rtype: L{server.Session} )r)rVrprWrsessionFactorys r*sessionFactoryWithClockzDRequestTests.test_getSessionExpired..sessionFactoryWithClock*s%T3/G$G Nr,N)r rrrrrrrVrZrprrrrSrTrar]rp) r(rVr&rBrqinitialSession newSessionrrps @@r*test_getSessionExpiredz#RequestTests.test_getSessionExpireds {{8,,./ N..A&  $,,5 ++-  n334'')   ))* 4 N.. ?r,c\t}tj|d}|jdd|j d|j ddd|j jj}|j|jd|jd |y ) zf L{Request} handles OPTIONS * requests by doing a fast-path return of 200 OK. r rrrsOPTIONS*HTTP/1.1sHTTP/1.1 200 OKContent-Length: 0 N rrrrrrrrArrrrr(r&rBresponses r*test_OPTIONSStarzRequestTests.test_OPTIONSStarJs N..A&+! D+>;;&&//1 ++,>?@ .9r,ct}tj|d}|jdd|j d|j ddd|j jj}|j|jd|jd ||jd |y ) z L{Request} handles any non-OPTIONS verb requesting the * path by doing a fast-return 405 Method Not Allowed, indicating only the support for OPTIONS. r rrrrrvrwsHTTP/1.1 405 Method Not AllowedrxsAllow: OPTIONS Nryrzs r*test_rejectNonOPTIONSStarz&RequestTests.test_rejectNonOPTIONSStarYs N..A&+!k:;;&&//1 ++,NOP .9 +X6r,ct}|jd|tj|}t }||_tj |d}||_|jdd|jd|jddd|jd |jjjjy ) zV Responses with no length do not have a default content-type applied. r,r rrrr/rwr8N)rFrZrrrrVrrrrrrrArr)r(rrVr&rBs r*-test_noDefaultContentTypeOnZeroLengthResponsez:RequestTests.test_noDefaultContentTypeOnZeroLengthResponsejs#$ sE"{{5! N..A& +!k: '*;*;*C*C*L*L*N*T*T*VWr,ct}|jd|tj|}t }||_tj |d}||_|jdd|jd|jddd|jjj}|j|jd |jd |j!y ) zX Responses with a 204 status code have no default content-type applied. r,r rrrrrrwsHTTP/1.1 204 No Content r8N)rKrZrrrrVrrrrrrArrrrr)r(rrVr&rBr{s r*&test_noDefaultContentTypeOn204Responsez3RequestTests.test_noDefaultContentTypeOn204Response{s"# sE"{{5! N..A& +!k:$$,,557 ++,JKL (..*:;r,ctjt}|jd|j |j t y)z L{http.Request} creates a L{BytesIO} if the content length is small and the site doesn't offer to create one. iN)rrrrrncontentrrAs r*test_defaultSmallContentFilez)RequestTests.test_defaultSmallContentFiles6 ..0*% goow7r,ctjt}|jdt ||j y)z L{http.Request} creates a temporary file on the filesystem if the content length is larger and the site doesn't offer to create one. iNrrrrr!rrAs r*test_defaultLargerContentFilez*RequestTests.test_defaultLargerContentFiles0 ..0&!#D'//:r,ctjt}|jdt ||j y)z L{http.Request} creates a temporary file on the filesystem if the content length is not known and the site doesn't offer to create one. NrrAs r*"test_defaultUnknownSizeContentFilez/RequestTests.test_defaultUnknownSizeContentFiles0 ..0$#D'//:r,cTgttjtj}fd}||_t }||_tj|}|jd|jdg|j|jy)z L{http.Request} uses L{Site.getContentFile}, if it exists, to get a file-like object for the request content. c*j|Sr%)append)length contentFilelengthss r*getContentFilezARequestTests.test_siteSuppliedContentFile..getContentFiles NN6 " r,90N) rrrrrrrrVrrr&rar)r(rVrrkrBrrs @@r*test_siteSuppliedContentFilez)RequestTests.test_siteSuppliedContentFiles i {{8,,./ -. ..)%  %'* k7??3r,N)!r-r.r/rDrrrr r'r*r.r0r3r5r7rLrOrQrTr_rcrgrkrmrtr|r~rrrrrrr0r,r*r r s <NQRORRN P;6;8;0;<<(6, * 7@$*@X :7"X"<&8;;4r,r c<eZdZdZdZdZdZdZdZdZ dZ y ) GzipEncoderTestsct|_tdd}tj|t j g}|jjjjd|y)N Some dataz text/plainfoo) rrkrrEncodingResourceWrapperrGzipEncoderFactoryrVrZ)r(staticResourcewrappeds r*rzGzipEncoderTests.setUpsZ#~ lL922 V6689  ""++FG>!4!4 4))$*=*=> > <("""r,ct)z$ # IResource.isLeaf NotImplementedErrorrs r*rzHeadlessResource.isLeaf "##r,ct)z1 # IResource.getChildWithDefault rrs r*rz$HeadlessResource.getChildWithDefaultrr,ct)z& # IResource.putChild r)r(pathchilds r*rZzHeadlessResource.putChildrr,N) r-r.r/rDrrCrrrZr0r,r*rrs$XN#$ $ $r,rc<eZdZdZd dZdZdZdZdZdZ d Z y) NewRenderTestsz- Tests for L{server.Request.render}. Nct}| t}|jjj d|d|j _tj|d}|jdd|jd|S)z Create a request object with a stub channel and install the passed resource at /newrender. If no resource is passed, create one. s newrenderr"r rr) rrrVrrZrr$rrrr)r(rr&rBs r*_getReqzNewRenderTests._getReqsn N  (*H   x8 ..A&+!r,c|j}|jddd|j|jjj j dd|j}|jddd|j|jjj j ddy)Nr /newrenderrrHEHr)rrr&rrAr splitlinesr(reqs r*testGoodMethodszNewRenderTests.testGoodMethodsslln FM;? ..779DDFrJHUlln FM;? ..779DDFrJHUr,c|j}|jddd|j|jd|j}|jddd|j|jdy)NsCONNECTrrs hlalauguG)rrr&coders r*testBadMethodszNewRenderTests.testBadMethodssdlln J {C 3'lln L-E 3'r,c||j}|jddd|j|jd|j |j j d|j jdd}td|jdD}|jgd |y ) z When trying to invoke a method not in the allowed method list, we get a response saying it is not allowed. POSTrrallowrc3<K|]}|jywr%)r).0hs r* z7NewRenderTests.test_notAllowedMethod..sCqCs,)rHEADrN) rrr&rrr< hasHeader getRawHeaderssortedr)r(r raw_headeralloweds r*test_notAllowedMethodz$NewRenderTests.test_notAllowedMethods lln G]K@ 3' ++55h?@((66x@C CJ,<,>{K  3' s# !S-.r,c ,Gdd}|tj}fd|_|j|}|j ddd|j j jjd\}}|j|jdd d d d d dtj|dddtj|dddddd g }|jdj|jd|y)zw When implemented C{render} method does not return bytes an internal server error is returned. ceZdZdefdZy)5NewRenderTests.test_noBytesResult..RiggedReprreturncy)Nzmy>reprr0rs r*__repr__z>NewRenderTests.test_noBytesResult..RiggedRepr.__repr__s r,N)r-r.r/strr r0r,r* RiggedReprrs !# !r,r"cSr%r0)rBrs r*rz3NewRenderTests.test_noBytesResult..s6r,rrrrirzz@ 500 - Request did not return bytesz z)

Request did not return bytes

z

Request:

<r rz#>

Resource:
<z0>

Value:
my>repr

z z asciiN)rrrCrrrrArrr&rr safe_reprjoinrx)r(r"no_bytes_resourcerBrrexpectedrs @r*test_noBytesResultz!NewRenderTests.test_noBytesResults  ! !$--/#9 ,,01 {C))11::<BB;O  s+   N  7 !!'*1R0!!"34Qr:      " 8,33GDDUK L 3 r,c|j}|jddd|j|jd|jj j }|jd||jd|y)a When an unsupported method response is generated, an HTML message will be displayed. That message should include a quoted form of the URI and, since that value come from a browser and shouldn't necessarily be trusted. rs#/gettableresource?value=