ϪffdZddlZddlZddlZddlmZddlmZddlm Z m Z ddl m Z ddl mZddl mZmZdd lmZmZmZdd lmZddlZdd lmZdd lmZmZdd lmZddlm Z m!Z!m"Z"ddl#m$Z$ddl%m&Z&ddl'm(Z(m)Z)ddl*m+Z+ddl,m-Z-ddl.m/Z/ddl0m Z ddl1m2Z2ddl3m4Z4m5Z5m6Z6ddl7m8Z8m9Z9m:Z:ddl;mZ>m?Z?ddl@mAZAGdde+e4jZCdZDGdd e4jZFeDeFZGGd!d"e jdZHGd#d$e4jZIeDeIZJee6jGd%d&eIZLeDeLZMGd'd(eIZNeDeNZOGd)d*e4jZQd+ZRGd,d-ZSGd.d/e jdeSZTGd0d1eTZUGd2d3eTZVGd4d5eTZWGd6d7e jdeSZXGd8d9e jdZYGd:d;e jdZZGd<d=e jdZ[Gd>d?e jdZ\d@Z]GdAdBe jdZ^GdCdDe2Z_GdEdFe jdZ`GdGdHe jdeSZaGdIdJe jdZbGdKdLe jdZcGdMdNe4jZdGdOdPe jdZeGdQdRe jdeSZfGdSdTe jdZgGdUdVe jdeSZhdWZiGdXdYe jdZjGdZd[e jdZkGd\d]e jZmGd^d_e jZnGd`dae jZoy)bz Test HTTP support. N)BytesIO)cycle)SequenceUnion)skipIf clear_cache)urlparse urlunsplit)directlyProvides providedByprovider) verifyObject)address)ConnectionDoneConnectionLost)Clock)EventLoggingObserverNonStreamingProducerStringTransport)globalLogPublisher)loopback) iterbytes networkString)proxyForInterface)Failure) DummyProducer)unittest)TestCase)http http_headersiweb)PotentialDataLoss _DataLoss_IdentityTransferDecoder) DummyChannelbytesLinearWhitespaceComponentssanitizedBytestextLinearWhitespaceComponents)assertIsFilesystemTemporaryceZdZdZy)._IDeprecatedHTTPChannelToRequestInterfaceProxyz Proxy L{_IDeprecatedHTTPChannelToRequestInterface}. Used to assert that the interface matches what L{HTTPChannel} expects. N)__name__ __module__ __qualname____doc__._makeRequestProxyLsd-f-=hGGr3)r r )r;r<s` r4_makeRequestProxyFactoryr=>s!H & 9(=> r3ceZdZdZdZy)DummyPullProducerHandlerz An HTTP request handler that registers a dummy pull producer to serve the body. The owner must call C{finish} to complete the response. c~t||_|jd|j|jdy)NF)r_actualProducersetResponseCoderegisterProducerselfs r4processz DummyPullProducerHandler.process]s33D9 S! d22E:r3Nr.r/r0r1rGr2r3r4r?r?Us ;r3r?ceZdZdZdZdZy) DateTimeTestszTest date parsing functions.ctdD]T}tjdd}tj|}tj |}|j ||Vy)Ni'ri5w)rangerandomrandintr datetimeToStringstringToDatetime assertEqual)rFitimetimestrtime2s r4 testRoundtripzDateTimeTests.testRoundtripisUu *A>>!Z0D++D1G))'2E   T5 )  *r3cgd}tjd}|D]'}|jtj||)|jtjdtjdy)N)sSun, 06 Nov 1994 08:49:37 GMTs06 Nov 1994 08:49:37 GMTsSunday, 06-Nov-94 08:49:37 GMTs06-Nov-94 08:49:37 GMTs Sunday, 06-Nov-1994 08:49:37 GMTs06-Nov-1994 08:49:37 GMTsSun Nov 6 08:49:37 1994sNov 6 08:49:37 1994) i 1%rYrYrs Thursday, 29-Sep-16 17:15:29 GMT) i r^ir)calendartimegmrQr rP)rF dateStringsdateInt dateStrings r4testStringToDatetimez"DateTimeTests.testStringToDatetimepsp  //"CD% IJ   T22:> H I   ! !"E F OO@ A r3N)r.r/r0r1rVrgr2r3r4rJrJfs&* r3rJceZdZdZy)DummyHTTPHandlerc.|jjdd|jj}|jd}|t |j }d|zdz|zdz}|j d|jd|j|jd|j|jd|j|jd d t|fz|j||jy) Nrcontent-lengths'''  rAsRequestsCommandsVersionContent-Lengths%d)contentseekread getHeaderstrencoderC setHeaderurimethod clientprotolenwritefinish)rFdatalengthrequests r4rGzDummyHTTPHandler.processs !Q||  " 12 >['')FV#e+d2X= S! z488, z4;;/ z4#3#34 (%3wl@STr3ct}t}tj}|j d}t ||}|j ||jd|j|j|j|j|jd|j|j|j|j|jd|jd|jd|j|j|j|jy)z If a timed out transport ends up calling C{connectionLost}, it prevents the force-closure of the transport. Nrrrr*)rrr rrrrrrrrrrrrs r4+test_transportNotAbortedAfterConnectionLostz8HTTP1_0Tests.test_transportNotAbortedAfterConnectionLostbs #% ""$((.*8U; *MN 001 //0  b  //0 //0  b%  a  //0 //0r3c|t}t}tj}|j d}d|j _t||}|j||jd|j|j|j|j|jd|j|j|j|j|jd|j|j|j|jy)zh If the L{HTTPChannel} has its c{abortTimeout} set to L{None}, it never aborts. Nrrl)rrr rrr abortTimeoutrrrrrrrrrs r4,test_transportNotAbortedWithZeroAbortTimeoutz9HTTP1_0Tests.test_transportNotAbortedWithZeroAbortTimeouts #% ""$((.)-&*8U; *MN 001 //0  b  //0 //0  e  //0 //0r3ct}t}tj}|j d}t ||}|j ||jd|j|j|j|j|jd|jd|j|j|j|j|jty)rNrrr`)rrr rrrrrrrrrrrrrs r4"test_connectionLostAfterForceClosez/HTTP1_0Tests.test_connectionLostAfterForceCloses #% ""$((.*8U; *MN 001 //0  b b  //0  ../ /r3cZt}tj}t|_|j |t |jD]}|j||jtd|j}|j||jy)zf Test that a L{http.Request} subclass with no queued kwarg works as expected. all doneNrrs r4test_noPipeliningApiz!HTTP1_0Tests.test_noPipeliningApis      0 dmm, !D NN4  ! ,-  !!%)?)?@r3ct}tj}t|_|j |t |jD]}|j||j}|j|d|jdt|j|jr[|jdt|j|jdj}|j|jr[|j}|j||jy)zW Test that pipelined requests get buffered, not processed in parallel. r3r*rN)rr rDelayedHTTPHandlerProxyrrrrrrrQrxoriginalrrr)rFrrrrr}s r4test_noPipeliningzHTTP1_0Tests.test_noPipelinings      2 dmm, !D NN4  !  $ C O,jj   QAJJ 0jjm,,G  " " $jj   !!%)?)?@r3N)r.r/r0rrrrbytes__annotations__rrrrrrrrrr2r3r4rrsf    BuXhuo6=>  A4(1 !UF1:1404A Ar3rceZdZdZgdZy) HTTP1_1TestssGET / HTTP/1.1 Accept: text/html POST / HTTP/1.1 Content-Length: 10 0123456789POST / HTTP/1.1 Content-Length: 10 0123456789HEAD / HTTP/1.1 ))HTTP/1.1 200 OKrrVersion: HTTP/1.1rrrr Command: POSTrsContent-Length: 21''' 10 0123456789''' r)rrs Command: HEADrrr3Nr.r/r0rrr2r3r4rrs  !r3rceZdZdZdgZy)HTTP1_1_close_TestsJGET / HTTP/1.1 Accept: text/html Connection: close GET / HTTP/1.0 )rsConnection: closerrrrrNrr2r3r4rrs    r3rc eZdZdZdZdZdZy) HTTP0_9TestssGET / HTTP/1.1 400 Bad Request c(|j||yr7)rQ)rFrexpectedResponses r4rz!HTTP0_9Tests.assertResponseEquals-s #34r3c,tjd)NzHTTP/0.9 not supported)rSkipTestrEs r4rzHTTP0_9Tests.test_noPipelining0s 899r3N)r.r/r0rrrrr2r3r4rr(sH;5:r3rc@eZdZdZdZddgZdZdZdZdZ d Z d Z y ) PipeliningBodyTestszl Pipelined requests get buffered and executed in the order received, not processed in parallel. stPOST / HTTP/1.1 Content-Length: 10 0123456789POST / HTTP/1.1 Transfer-Encoding: chunked a 0123456789 0 r)rrrrsContent-Length: 23s''' None 0123456789''' czt}tj}t|_|j |t |jD]}|j||j|jd|jdt|j|jr[|jdt|j|jdj}|j|jr[|j|j|jy)z Imitate a slow connection that delivers one byte at a time. The request handler (L{DelayedHTTPHandler}) is puppeted to step through the handling of each request. r3r*rN)rr rrrrrrrrQrrxrrrexpectedResponses)rFrrrr}s r4test_stepwiseTinyTubez)PipeliningBodyTests.test_stepwiseTinyTube\s      2 dmm, !D NN4  ! C( C O,jj   QAJJ 0jjm,,G  " " $jj !!!'')T-C-CDr3cZt}tj}t|_|j ||j |j|j|jd|jdt|j|jr[|jdt|j|jdj}|j|jr[|j|j|jy)z Imitate a fast connection where several pipelined requests arrive in a single read. The request handler (L{DelayedHTTPHandler}) is puppeted to step through the handling of each request. r3r*rN)rr rrrrrrrQrrxrrrr )rFrrr}s r4test_stepwiseDumpTruckz*PipeliningBodyTests.test_stepwiseDumpTruckvs      2  t}}% C( C O,jj   QAJJ 0jjm,,G  " " $jj !!!'')T-C-CDr3clt}tj}t|_|j |t |jD]8}|j||jt|jd:|j|j|jy)z Imitate a slow connection that delivers one byte at a time. (L{DummyHTTPHandler}) immediately responds, but no more than one r*N)rr rrrrrrrassertLessEqualrxrrr )rFrrrs r4test_immediateTinyTubez*PipeliningBodyTests.test_immediateTinyTubes      0 dmm, 5D NN4  QZZ! 4 5 !!!'')T-C-CDr3ct}tj}t|_|j ||j |j|j|j|jy)aR Imitate a fast connection where several pipelined requests arrive in a single read. The request handler (L{DummyHTTPHandler}) immediately responds. This doesn't check the at-most-one pending request invariant but exercises otherwise uncovered code paths. See GHSA-c8m8-j448-xjx7. N) rr rrrrrrrrr )rFrrs r4test_immediateDumpTruckz+PipeliningBodyTests.test_immediateDumpTrucks^      0  t}}% !!!'')T-C-CDr3cXt}tj}t|_|j ||j t|jzdz}|j|j|z|j|j|j|zy)a Imitate a fast connection where a so many pipelined requests arrive in a single read that backpressure is indicated. The request handler (L{DummyHTTPHandler}) immediately responds. This doesn't check the at-most-one pending request invariant but exercises otherwise uncovered code paths. See GHSA-c8m8-j448-xjx7. @see: L{http.HTTPChannel._optimisticEagerReadSize} rN) rr rrrr_optimisticEagerReadSizerxrrrrr )rFrroverLimitCounts r4test_immediateABiggerTruckz.PipeliningBodyTests.test_immediateABiggerTrucks      0 33s4==7IIBN t}}~56 !!!'')T-C-Cn-TUr3c t}tj}t|_|j ||j t|jz}td|dzD]U}|j|j|j|jddj|j|W|j|j|j|jdy)z When pipelined requests are received, we will optimistically continue receiving data up to a specified limit, then pause the transport. @see: L{http.HTTPChannel._optimisticEagerReadSize} r* producingz(state was {state!r} after {x} iterations)statexpausedN)rr rrrrrrxrrLrrQ producerStateformatr)rFrr underLimitrs r4test_pipeliningReadLimitz,PipeliningBodyTests.test_pipeliningReadLimits      2 //3t}}3EE q*q.) A NN4== )   :AA//QB   t}}% !//84r3N) r.r/r0r1rr r rrrrr!r2r3r4r r 4sF    &E4E4E(E(V,5r3r cDeZdZdZGddej ZdZdZy) ShutdownTestszM Tests that connections can be shut down by L{http.Request} objects. ceZdZdZdZy)!ShutdownTests.ShutdownHTTPHandlerzL A HTTP handler that just immediately calls loseConnection. c$|jyr7)loseConnectionrEs r4rGz)ShutdownTests.ShutdownHTTPHandler.processs    !r3NrHr2r3r4ShutdownHTTPHandlerr%s   "r3r(s1POST / HTTP/1.1 Content-Length: 10 0123456789cFt}tj}t|j|_|j ||j|j|j|j|j}|j|dy)zi Calling L{http.Request.loseConnection} causes the transport to be disconnected. r3N) rr rr=r(rrrr}rrrrQ)rFrrrs r4test_losingConnectionz#ShutdownTests.test_losingConnectionsz      3D4L4LM  t||$ (  $r3N) r.r/r0r1r Requestr(r}r*r2r3r4r#r#s$"dll"UG%r3r#c"eZdZdZdZdZdZy) SecurityTestsz] Tests that L{http.Request.isSecure} correctly takes the transport into account. ctj}tj}|j |tj |}|j |jy)z Calling L{http.Request.isSecure} when the channel is backed with a secure transport will return L{True}. N)r&SSLr rrr+risSecurerFrrreqs r4 test_isSecurezSecurityTests.test_isSecuresM         ll1o  'r3ctj}tj}|j |tj |}|j |jy)z Calling L{http.Request.isSecure} when the channel is not backed with a secure transport will return L{False}. N)r&TCPr rrr+rr0r1s r4test_notSecurezSecurityTests.test_notSecuresO         ll1o (r3cVtj}tj}|j |tj |}|j j||jd|j|j|jy)zt After a request is finished, calling L{http.Request.isSecure} will always return L{False}. rAN) r&r/r rrr+rappendrCrzrr0r1s r4test_notSecureAfterFinishz'SecurityTests.test_notSecureAfterFinish%sx         ll1o # C   (r3N)r.r/r0r1r3r6r9r2r3r4r-r- s ( ) )r3r-c@eZdZdZdZdZeej ddZ dZ dZ dZ eej dd Z eejd d Zd Zd ZdZeej ddZeej ddZy)GenericHTTPChannelTestsz Tests for L{http._genericHTTPChannelProtocol}, a L{HTTPChannel}-alike which can handle different HTTP protocol channels. rctjd}t|_|j |t |j D]}|j||jtd|jS)z{ Run a request using the specific instance of a transport. Returns the negotiated protocol string. r3r) r "_genericHTTPChannelProtocolFactoryrrrrrrrr_negotiatedProtocol)rFtrrs r4'_negotiatedProtocolForTransportInstancez?GenericHTTPChannelTests._negotiatedProtocolForTransportInstanceDsm  3 3C 80 dmm, !D NN4  ! ,-$$$r3zHTTP/2 support not presentc t}tjd}t|_d|_|j |_t}d|_|j|tj|jtjtjdtjd|jd}|j!d|j#|j$d|j'|j(tj|jtjtjdtjdy)zg When the transport is switched to H2, the HTTPChannel timeouts are cancelled. r3rh2 cancelledFrN)rr r=rrrrrnegotiatedProtocolrhamcrest assert_thatgetDelayedCallscontains has_propertyequal_torrQr>rrC)rFrrr h11Timeouts r4test_h2CancelsH11Timeoutz0GenericHTTPChannelTests.test_h2CancelsH11TimeoutRs2   3 3C 80 oo  $    ! ! #   %%%%e,  **,Q/  s ..6  ,,-  ! ! #   %%%%e,  r3c^t}|j|}|j|dy)z If the transport has no support for protocol negotiation (no negotiatedProtocol attribute), HTTP/1.1 is assumed. http/1.1N)rr@rQrFrrDs r4test_protocolUnspecifiedz0GenericHTTPChannelTests.test_protocolUnspecifieds.  !II!L +[9r3clt}d|_|j|}|j|dy)z If the transport has no support for protocol negotiation (returns None for negotiatedProtocol), HTTP/1.1 is assumed. NrNrrDr@rQrOs r4test_protocolNonez)GenericHTTPChannelTests.test_protocolNones6  #!II!L +[9r3clt}d|_|j|}|j|dy)zi If the transport reports that HTTP/1.1 is negotiated, that's what's negotiated. rNNrRrOs r4 test_http11z#GenericHTTPChannelTests.test_http11s6  *!II!L +[9r3clt}d|_|j|}|j|dy)z} If the transport reports that HTTP/2 is negotiated and HTTP/2 is present, that's what's negotiated. rBNrRrOs r4test_http2_presentz*GenericHTTPChannelTests.test_http2_presents6  $!II!L +U3r3zHTTP/2 support presentcht}d|_|jt|j|y)z If the transport reports that HTTP/2 is negotiated and HTTP/2 is not present, an error is encountered. rBN)rrD assertRaises ValueErrorr@rFrs r4test_http2_absentz)GenericHTTPChannelTests.test_http2_absents1  $    8 8  r3cht}d|_|jt|j|y)z If the transport reports that a protocol other than HTTP/1.1 or HTTP/2 is negotiated, an error occurs. ssmtpN)rrDrYAssertionErrorr@r[s r4test_unknownProtocolz,GenericHTTPChannelTests.test_unknownProtocols1  &    8 8  r3ctjd}d|j_|j |jdy)zK The C{factory} attribute is taken from the inner channel. r3FooN)r r=rrrQ)rFrs r4 test_factoryz$GenericHTTPChannelTests.test_factorys4  3 3C 8#  F+r3ct}tj|}|jd}|j |j |j |j |j j |j y)z If C{callLater} is patched onto the L{http._GenericHTTPChannelProtocol} then we need to propagate it through to the backing channel. rN)rr rrrQrr)rFrrrs r4*test_GenericHTTPChannelPropagatesCallLaterzBGenericHTTPChannelTests.test_GenericHTTPChannelPropagatesCallLaterse ""51((. ++U__= **44eooFr3c:t}tj|}|jd}|j |j |j |j |j j |j t}d|_t|_ |j||jd|j |j |j |j |j j |j y)z If C{callLater} is patched onto the L{http._GenericHTTPChannelProtocol} then we need to propagate it across onto a new backing channel after upgrade. rdNrBP) rr rrrQrrrrDrirrrrFrrrrs r4'test_genericHTTPChannelCallLaterUpgradez?GenericHTTPChannelTests.test_genericHTTPChannelCallLaterUpgrades""51((. ++U__= **44eooF#% ', $"2 * d# ++U__= **44eooFr3c~t}d|_tjd}t|_|j ||j}|j|j||jd|j|j||j|j|jy)z The L{_GenericHTTPChannelProtocol} will unregister its proxy channel from the transport if upgrade is negotiated. rBr3rgN) rrDr r=rrrrassertIsproducerr assertIsNot)rFrgenericProtocoloriginalChannels r4test_unregistersProducerz0GenericHTTPChannelTests.test_unregistersProducers $% ', $AA#F)>&&&y1)22 i((/: $$T* ++_= i((/*B*BCr3N)r.r/r0r1rr@rr H2_ENABLEDrLrPrSrUrWr\r_rbrerirpr2r3r4r;r;5s    %  !=>/ ?/ b:::  !=>4?4 DOO56  7    , G  !=>G?G0  !=>D?Dr3r;cNeZdZdddddZdZdZdZdZdZdZ d Z d Z d Z d Z y )HTTPLoopbackTestsrrHTTP/1.0s21)srequestscommandsversionrkrcZd|_|j|d|j|dy)Nr*rt200) gotStatusrQrFversionrmessages r4 _handleStatuszHTTPLoopbackTests._handleStatuss) +. (r3c6d|_|j|dy)Nr*r) gotResponserQ)rFr{s r4_handleResponsez!HTTPLoopbackTests._handleResponse#s :;r3c|jdz|_|j|j|j|yNr*) numHeadersrQrlower)rFkeyrs r4 _handleHeaderzHTTPLoopbackTests._handleHeader's3//A- --ciik:EBr3cJd|_|j|jdy)Nr*) gotEndHeadersrQrrEs r4_handleEndHeadersz#HTTPLoopbackTests._handleEndHeaders+s !,r3cBtj}t|_t }|j |_|j|_|j|_ |j|_ tj||}|j|j |Sr7)r rrrrr~handleResponser handleHeaderrhandleEndHeadersr{ handleStatusr loopbackAsync addCallback_cbTestLoopback)rFserverclientds r4 testLoopbackzHTTPLoopbackTests.testLoopback/s!!# 5#% $ 4 4"00"&"8"8"00  " "66 2 d**+r3c|jr|jr |js;tdj |j|j|jg|`|`|`|`y)Nzdidn't get all callbacks {})rwr}r RuntimeErrorrr)rFignoreds r4rz!HTTPLoopbackTests._cbTestLoopback;sf4#3#38J8J-44^^T%5%5t7I7IJ      N Or3N)r.r/r0rrrwr}rr{r~rrrrr2r3r4rsrssJ O JIKM) <C-  r3rsc tjtd}|jD]*\}}|jj t ||,|S)zR Make a request with the given request headers for the persistence tests. F)r r+r&itemsrequestHeaders setRawHeadersr)rr} headerNamevs r4 _prequestrHsQll<>51G K A,,]:-FJK Nr3c.eZdZdZdZdZdZdZdZy)PersistenceTestsz0 Tests for persistent HTTP connections. cTtj|_t|_yr7)r rrrr}rEs r4setUpzPersistenceTests.setUpWs'')  { r3c|jj|jd}|j||j gt |jj jy)zl After being used for an I{HTTP/0.9} request, the L{HTTPChannel} is not persistent. sHTTP/0.9NrcheckPersistencer}rrQlistresponseHeadersgetAllRawHeadersrFpersists r4 test_http09zPersistenceTests.test_http09[T ,,// kJ ! T$,,">">"O"O"QRSr3c|jj|jd}|j||j gt |jj jy)zl After being used for an I{HTTP/1.0} request, the L{HTTPChannel} is not persistent. rtNrrs r4 test_http10zPersistenceTests.test_http10drr3c|jj|jd}|j||j gt |jj jy)zh After being used for an I{HTTP/1.1} request, the L{HTTPChannel} is persistent. HTTP/1.1N)rrr}rrQrrrrs r4rUzPersistenceTests.test_http11msR ,,// kJ   T$,,">">"O"O"QRSr3ctdg}|jj|d}|j||j ddgfgt |j jy)z After being used for an I{HTTP/1.1} request with a I{Connection: Close} header, the L{HTTPChannel} is not persistent. sclose) connectionrs ConnectionN)rrrrrQrrr)rFr}rs r4test_http11Closez!PersistenceTests.test_http11Closevsf z2,,//E ! hZ ( ) ((99; < r3N) r.r/r0r1rrrrUrr2r3r4rrRs##TTT  r3rcLeZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z y ) IdentityTransferEncodingTestsz0 Tests for L{_IdentityTransferDecoder}. cg|_g|_d|_t|j|jj|jj|_y)z Create an L{_IdentityTransferDecoder} with callbacks hooked up so that calls to them can be inspected. rN)r{rz contentLengthr%r8decoderrEs r4rz#IdentityTransferEncodingTests.setUpsG   /    0 0$++2D2D  r3c|jjd|jz|j|jd|jzg|j|j dgy)aC If L{_IdentityTransferDecoder.dataReceived} is called with a byte string with length equal to the content length passed to L{_IdentityTransferDecoder}'s initializer, the data callback is invoked with that string and the finish callback is invoked with a zero-length string. rr3NrrrrQr{rzrEs r4test_exactAmountReceivedz6IdentityTransferEncodingTests.test_exactAmountReceivedsY !!$););";< TD,>,>%>$?@ se,r3c|jjd|j|jdg|j|jg|jjd|j dz z|j|jdd|j dz zg|j|jdgy)a3 If L{_IdentityTransferDecoder.dataReceived} is called multiple times with byte strings which, when concatenated, are as long as the content length provided, the data callback is invoked with each string and the finish callback is invoked only after the second call. ryr*r3N)rrrQr{rzrrEs r4test_shortStringsz/IdentityTransferEncodingTests.test_shortStringss !!$' TF+ b) !!$$*<*,>%>$?@ tf-r3cBgfd}td|jj|jd|j gjddj t |j tdjdy)z If data is passed to L{_IdentityTransferDecoder.dataReceived} after the finish callback has been invoked, C{RuntimeError} is raised. cz jdy#t$rjtYywxYw)Nfoo)r BaseExceptionr8r)rrfailuress r4rzzJIdentityTransferEncodingTests.test_rejectDataAfterFinished..finishs3 +$$V,  + * +s "::sxxxxrrz;_IdentityTransferDecoder cannot decode data after finishingN) r%r{r8rrQtraprrrr)rFrzrrs @@r4test_rejectDataAfterFinishedz:IdentityTransferEncodingTests.test_rejectDataAfterFinisheds  + +1dii.>.>GX& 2&T" &   !! " I r3cg}g}td|j|j}|jd|j|dg|jd|j|ddg|j|gy)z If L{_IdentityTransferDecoder} is constructed with L{None} for the content length, it passes all data delivered to it through to the data callback. Nrr)r%r8rrQ)rFr{rzrs r4test_unknownContentLengthz7IdentityTransferEncodingTests.test_unknownContentLengthsv *4fmmLT" v&T" d|, $r3ct|j|jd|j|jdy)z Check the decoder's data and finish callbacks and make sure they are None in order to help avoid references cycles. N)assertIdentical dataCallbackfinishCallback)rFrs r4_verifyCallbacksUnreferencedz:IdentityTransferEncodingTests._verifyCallbacksUnreferenceds0 W1148 W33T:r3c|jjd|jdz z|jt|jj |j |jy)z L{_IdentityTransferDecoder.noMoreData} raises L{_DataLoss} if it is called and the content length is known but not enough bytes have been delivered. rr*N)rrrrYr$ noMoreDatarrEs r4test_earlyConnectionLosez6IdentityTransferEncodingTests.test_earlyConnectionLosesR !!$$*<*r3c(g}g}tj|j|j}tdD]}|j ||j |gd|j |dg|j |j gy)z{ L{_ChunkedTransferDecoder.dataReceived} decodes chunks broken up and delivered in multiple calls. 3 abc 5 12345 0 abc12345r3Nr rr8rrrQ_trailerHeadersrFrrrss r4 test_shortz'ChunkedTransferEncodingTests.test_shorts   ( (8?? CAB A NN1   LM C5) **B/r3cg}g}tj|j|j}|jd|jd|jd|j |ddg|j |dgy)zx L{_ChunkedTransferDecoder.dataReceived} delivers partial chunk data as soon as it is received. s a; 12345s67890s 0; ...rs...Nr)rFr{rrs r4 test_longz&ChunkedTransferEncodingTests.test_long+st   ( (hoo F ~& x  +, (34 F8,r3c4g}g}tj|j|j}|jdt dD]$}|j||jd&|j |gd|j |dgy)zr L{_ChunkedTransferDecoder.dataReceived} is robust against receiving a zero-length input. r3rrN)r rr8rrrQ)rFchunksrrrs r4 test_emptyz'ChunkedTransferEncodingTests.test_empty9s   ( ( H sAB A NN1  NN3   !QR C5)r3cg}tj|jd}|jd|j |dgy)z L{_ChunkedTransferDecoder.dataReceived} doesn't treat CR LF pairs embedded in chunk bodies specially. Ns2  rrs r4 test_newlinesz*ChunkedTransferEncodingTests.test_newlinesHs>   ( (4 8 '( WI&r3cg}tj|jd}|jd|j |dgy)zd L{_ChunkedTransferDecoder.dataReceived} disregards chunk-extension fields. Ns3; x-foo=bar abc rrrs r4test_extensionsz,ChunkedTransferEncodingTests.test_extensionsRs>   ( (4 8 12 VH%r3cd}d}d}||z|zD]W}dt|fzdz}tjdd}|jtj|j |Yy) z L{_ChunkedTransferDecoder.dataReceived} raises L{_MalformedChunkedDataError} when the chunk extension fields contain invalid characters. This is a potential request smuggling vector: see GHSA-c2jg-hw38-jrqq. s \s3;  abc cyr7r2rs r4zGChunkedTransferEncodingTests.test_extensionsMalformed..mr3cyr7r2rs r4rzGChunkedTransferEncodingTests.test_extensionsMalformed..nrr3N)rr rrY_MalformedChunkedDataErrorr)rFinvalidControlinvalidDelimiter invalidDelrr{rs r4test_extensionsMalformedz5ChunkedTransferEncodingTests.test_extensionsMalformed\s P ! "22Z? UAE1$K'.8D,,A   d==q~~t T  Ur3ctjdd}|jtj|jddtj zzdzy)a( L{_ChunkedTransferDecoder.dataReceived} raises L{_MalformedChunkedDataError} when the chunk size line exceeds 4 KiB. This applies even when the data has already been received and buffered so that behavior is consistent regardless of how bytes are framed. Ns3;.rr rrYr rmaxChunkSizeLineLengthrFrs r4test_oversizedChunkSizeLinez8ChunkedTransferEncodingTests.test_oversizedChunkSizeLinersL  ( (t 4   + + NN D4666 6 G r3ctjdd}|jtj|jdtj dzzy)a  L{_ChunkedTransferDecoder.dataReceived} raises L{_MalformedChunkedDataError} when the amount of data buffered while looking for the end of the chunk size line exceeds 4 KiB so that buffering does not continue without bound. Nrr*rrs r4"test_oversizedChunkSizeLinePartialz?ChunkedTransferEncodingTests.test_oversizedChunkSizeLinePartialsG  ( (t 4   + + NN D//!3 4 r3ctjdd}|jtj|jdy)z L{_ChunkedTransferDecoder.dataReceived} raises L{_MalformedChunkedDataError} when the chunk size can't be decoded as a base-16 integer. cyr7r2rs r4rzFChunkedTransferEncodingTests.test_malformedChunkSize..rr3cyr7r2rs r4rzFChunkedTransferEncodingTests.test_malformedChunkSize..rr3s bloop abc Nr rrYr rrs r4test_malformedChunkSizez4ChunkedTransferEncodingTests.test_malformedChunkSizes<  ( (      + +Q^^=P r3ctjdd}|jtj|jdy)z L{_ChunkedTransferDecoder.dataReceived} raises L{_MalformedChunkedDataError} when the chunk size is negative. cyr7r2rs r4rzNChunkedTransferEncodingTests.test_malformedChunkSizeNegative..rr3cyr7r2rs r4rzNChunkedTransferEncodingTests.test_malformedChunkSizeNegative..rr3s -3 abc Nrrs r4test_malformedChunkSizeNegativez.rr3cyr7r2rs r4rzIChunkedTransferEncodingTests.test_malformedChunkSizeHex..rr3s 0x3 abc Nrrs r4test_malformedChunkSizeHexz7ChunkedTransferEncodingTests.test_malformedChunkSizeHexs<  ( (      + +Q^^=N r3ctjdd}|jtj|jdy)z L{_ChunkedTransferDecoder.dataReceived} raises L{_MalformedChunkedDataError} when the chunk is followed by characters other than C{\r\n}. cyr7r2rs r4rzEChunkedTransferEncodingTests.test_malformedChunkEnd..rr3cyr7r2rs r4rzEChunkedTransferEncodingTests.test_malformedChunkEnd..rr3s 3 abc!!!!Nrrs r4test_malformedChunkEndz3ChunkedTransferEncodingTests.test_malformedChunkEnds;  ( (      + +Q^^_ r3cg}tjd|j}|jd|j |dgy)z L{_ChunkedTransferDecoder.dataReceived} interprets a zero-length chunk as the end of the chunked data stream and calls the completion callback. N0 r3rrFrrs r4 test_finishz(ChunkedTransferEncodingTests.test_finishs=   ( (x ? |$ C5)r3cg}tjd|j}|jd|j |dgy)z L{_ChunkedTransferDecoder.dataReceived} passes any bytes which come after the terminating zero-length chunk to the completion callback. Ns 0 hellohellorr)s r4 test_extraz'ChunkedTransferEncodingTests.test_extras>   ( (x ? () H:.r3ctjdd}|jd|jt|jdy)z L{_ChunkedTransferDecoder.dataReceived} raises C{RuntimeError} if it is called after it has seen the last chunk. Ncyr7r2rs r4rzAChunkedTransferEncodingTests.test_afterFinished..rr3r(r,)r rrrYrrs r4test_afterFinishedz/ChunkedTransferEncodingTests.test_afterFinisheds9  ( (/A B |$ ,Ar3ctjdd}|jd|jt|j }|j t|dy)z L{_ChunkedTransferDecoder.noMoreData} raises L{_DataLoss} if it is called and the end of the last trailer has not yet been received. Ncyr7r2r0s r4rzGChunkedTransferEncodingTests.test_earlyConnectionLose..rr3s0 zYChunked decoder in 'TRAILER' state, still expecting more data to get to 'FINISHED' state.)r rrrYr$rrQrr)rFparserexcs r4rz5ChunkedTransferEncodingTests.test_earlyConnectionLosesW --d4FGJ' 6+<+<=  H * r3cttjdd}|jd|jy)z L{_ChunkedTransferDecoder.noMoreData} does not raise any exception if it is called after the terminal zero length chunk is received. Ncyr7r2r0s r4rzJChunkedTransferEncodingTests.test_finishedConnectionLose..rr3r()r rrr)rFr4s r4rz8ChunkedTransferEncodingTests.test_finishedConnectionLoses1 --d4FGL)r3cggfd}tjd|jd|jg|jdgy)z L{_ChunkedTransferDecoder.noMoreData} can be called from the finished callback without raising an exception. c jjdy#t$rjtYywxYwNT)rr8rr)extraerrorsr4 successess r4rzOChunkedTransferEncodingTests.test_reentrantFinishedNoMoreData..finishedsC '!!#  &! ) gi( )s%"A  A Nr(T)r rrrQ)rFrr<r4r=s @@@r4 test_reentrantFinishedNoMoreDataz=ChunkedTransferEncodingTests.test_reentrantFinishedNoMoreDatasX   '--dH=L) $ TF+r3c.g}g}tj|j|j}|jd|jd|j |gd|j |dg|j |j ddgy)z L{_ChunkedTransferDecoder.dataReceived} decodes chunked-encoded data and ignores trailer headers which come after the terminating zero-length chunk. rs\a 0123456789 0 Server-Timing: total;dur=123.4 Expires: Wed, 21 Oct 2015 07:28:00 GMT rr3Server-Timing: total;dur=123.4s&Expires: Wed, 21 Oct 2015 07:28:00 GMTN)r rr8rrQr)rFrrrs r4test_trailerHeadersz0ChunkedTransferEncodingTests.test_trailerHeaderss   ( (8?? C 45  w  => C5)   19  r3c*g}g}tj|j|j}tdD]}|j ||j |gd|j |dg|j |j dgy)z L{_ChunkedTransferDecoder.dataReceived} decodes chunks of input with tailer header broken up and delivered in multiple calls. s73 abc 5 12345 0 Server-Timing: total;dur=123.4 rr3r@Nrrs r4test_shortTrailerHeaderz4ChunkedTransferEncodingTests.test_shortTrailerHeader(s   ( (8?? C T  A NN1   LM C5) **-N,OPr3ctjdd}d|_|jtj|j dy)z L{_ChunkedTransferDecoder.dataReceived} raises L{_MalformedChunkedDataError} when the trailing headers data is too long. cyr7r2rs r4rzHChunkedTransferEncodingTests.test_tooLongTrailerHeader..>rr3cyr7r2rs r4rzHChunkedTransferEncodingTests.test_tooLongTrailerHeader..?rr3rs43 abc 0 Total-Trailer: header;greater-then=10 N)r r_maxTrailerHeadersSizerYr rrs r4test_tooLongTrailerHeaderz6ChunkedTransferEncodingTests.test_tooLongTrailerHeader8sE  ( (   $&    + + NN M r3ctjdd}d|_|jd|jd|j tj |jdy)z L{_ChunkedTransferDecoder.dataReceived} raises L{_MalformedChunkedDataError} when the trailing headers data is too long and doesn't have final CRLF characters. cyr7r2rs r4rzKChunkedTransferEncodingTests.test_unfinishedTrailerHeader..Orr3cyr7r2rs r4rzKChunkedTransferEncodingTests.test_unfinishedTrailerHeader..Prr3rs3 abc 0 01234567 AN)r rrGrrYr rs r4test_unfinishedTrailerHeaderz9ChunkedTransferEncodingTests.test_unfinishedTrailerHeaderHs`  ( (   $&  34 u   + + NN  r3N)r.r/r0r1rrrrrrr rrrrr"r&r*r-r1rrr>rArCrHrNr2r3r4rr s} ? 0 - *'&U,           */B  ,* .Q   r3rc4eZdZgdZdZdZdZddZdZy) ChunkingTests)sabcvr3sfdfsd423s Ffasfas s 523523 fsdfs4234c|jD]M}djtj|}|j |dftj |O|j ttj d|j ttj d|j ttj dy)Nr3s-5 malformed! s0xa malformed! s0XA malformed! )stringsjoinr toChunkrQ fromChunkrYrZ)rFrchunkeds r4 testChunkszChunkingTests.testChunksbs @Ahht||A/G   aXt~~g'> ? @ *dnn6MN *dnn6NO *dnn6NOr3c dj|jDcgc]&}djtj|(c}}g}d}t |D]1}||z} tj |\}}|j |3|j||jycc}w#t$rYawxYw)Nr3) rSrRr rTrrUr8rZrQ)rFr?rVresultbuffercr{s r4testConcatenatedChunksz$ChunkingTests.testConcatenatedChunksjs((t||L!CHHT\\!_5LM7# AaZF #~~f5 f d#   .M  s+B,$)B11 B=<B=c~t}tj}|j|tj|d}|j dd|_|jjddg|jd|jd|j|jdgy ) zV Test that the L{HTTPChannel} correctly chunks responses when needed. FrArtestlemurHelloWorld!r Test: lemurTransfer-Encoding: chunkeds5 Hello 6 World! N) rr rrr+rCrwrrryrr)rFtransrr2s r4test_chunkedResponsesz#ChunkingTests.test_chunkedResponsesws !""$u%ll7E* C % ))'H:> ( ) !! KKM  r3Nc tj}|rt||_|j dd}|j dd\}}t }|j||j|dztt||zdzD]Y}|jjrnA|jdjtj|||z|dz|z[|jdjtjd|jt!d|S)z Execute a web request based on plain text content, chunking the request payload. This is a stripped-down, chunking version of ParsingTests.runRequest. rlrrr*r3r)r rr=rreplacerrrrrLrxrrrSrTrr) rF httpRequestr chunkSizerheaderrrposs r4runChunkedRequestzChunkingTests.runChunkedRequests""$ %=n%MG "!))%9 "((a8 #% y)Vk12Ti/!34 C  ..  d3?cAg=R&STU   SXXdll3&789wz23r3c:gGfddtj}d}|j||d}|j|jj d|jt d|jdjd d giy ) a Test that chunked uploads are actually processed into args. This is essentially a copy of ParsingTests.test_multipartFormData, just with chunking put in. This fails as of twisted version 18.9.0 because of bug #9678. ceZdZfdZy)7ChunkingTests.test_multipartFormData..MyRequestcjj||jd|jyNsdoner8ryrzrF processeds r4rGz?ChunkingTests.test_multipartFormData..MyRequest.process&  & 7# r3Nr~rusr4 MyRequestrp r3rxsPOST / HTTP/1.0 Content-Type: multipart/form-data; boundary=AaB03x Transfer-Encoding: chunked --AaB03x Content-Type: text/plain Content-Disposition: form-data; name="text" Content-Transfer-Encoding: quoted-printable abasdfg --AaB03x-- r)rjHTTP/1.0 200 OK doner*rtextabasdfgN)r r+rmrQrrrxr8rFrxr2rrus @r4test_multipartFormDataz$ChunkingTests.test_multipartFormDatas     ((i1(E **0024RS Y+ 1**Wzl,CDr3r) r.r/r0rRrWr\rfrmr~r2r3r4rPrP_s#UGP / 8@!Er3rPceZdZdZdZd(dZdZdZdZdZ d Z d Z d Z d Z d ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZ d Z!d!Z"d"Z#d#Z$d$Z%d%Z&d&Z'd'Z(y)) ParsingTestsz7 Tests for protocol parsing in L{HTTPChannel}. cd|_y)NF didRequestrEs r4rzParsingTests.setUps r3Nc|stj}|rt||_|j dd}t }|j |t|D]+}|jjrn|j|-|jtd|r|j|j|S|j|j|S)a Execute a web request based on plain text content. @param httpRequest: Content for the request which is processed. Each L{" "} will be replaced with L{" "}. @type httpRequest: C{bytes} @param requestFactory: 2-argument callable returning a Request. @type requestFactory: C{callable} @param success: Value to compare against I{self.didRequest}. @type success: C{bool} @param channel: Channel instance over which the request is processed. @type channel: L{HTTPChannel} @return: Returns the channel used for processing the request. @rtype: L{HTTPChannel} rlrr)r rr=rrhrrrrrrrrrrr)rFrirsuccessrrrs r4 runRequestzParsingTests.runRequests(&&(G %=n%MG "!))%9 #% y)k* 'D  ..   & ' wz23  OODOO ,   T__ -r3cLdj|}gGfddtj}|j||d}|j |j j d|j|j j|j gy)aJ Execute a HTTP request and assert that it is rejected with a 400 Bad Response and disconnection. @param requestLines: Plain text lines of the request. These lines will be joined with newlines to form the HTTP request that is processed. @type requestLines: C{list} of C{bytes} rlceZdZfdZy)5ParsingTests.assertRequestRejected..MyRequestcHj||jyr7r8rzrts r4rGz=ParsingTests.assertRequestRejected..MyRequest.process  & r3Nr~rwsr4rxr r3rxFrrN) rSr r+rrQrrrr)rF requestLinesrirxrrus @r4assertRequestRejectedz"ParsingTests.assertRequestRejected sjj.      //+y%/H     # # % /  ))778 B'r3c,gGfddtj}d}|j||d}|j|jj d|j |jj|jgy)z When client sends invalid HTTP method containing non-ascii characters HTTP 400 'Bad Request' status will be returned. ceZdZfdZy):ParsingTests.test_invalidNonAsciiMethod..MyRequestcHj||jyr7rrts r4rGzBParsingTests.test_invalidNonAsciiMethod..MyRequest.process+rr3Nr~rwsr4rxr*rr3rxsGE© / HTTP/1.1 rrN)r r+rrQrrrr)rFrxbadRequestLinerrus @r4test_invalidNonAsciiMethodz'ParsingTests.test_invalidNonAsciiMethod#s{      ://.)Q? **0024WX ))778 B'r3c2gGfddtj}dD]t\}}tjdj ||f}d|zdz}|j ||dj }|j||f|jvy) z L{HTTPChannel} provides username and password information supplied in an I{Authorization} header to the L{Request} which makes it available via its C{getUser} and C{getPassword} methods. ceZdZfdZy),ParsingTests.test_basicAuth..Requestcr|j|jf|_j|yr7getUser getPassword credentialsr8rFrs r4rGz4ParsingTests.test_basicAuth..Request.process>+$(LLND4D4D4F#G %r3Nr~rsr4r+r= &r3r+))rbar)r,sthere:z:$GET / HTTP/1.0 Authorization: Basic  rN) r r+base64 b64encoderSrrrQr)rFr+urrfr2rs @r4test_basicAuthzParsingTests.test_basicAuth5s  &dll & ? 6DAq  Aq6!23A81.MyRequestcHj||jyr7rrts r4rGz4ParsingTests.test_headers..MyRequest.processQrr3Nr~rwsr4rxrPrr3rx)GET / HTTP/1.0Foo: bars baz: Quuxs baz: quuxr3r3rlrrrsbAzsQuuxquuxNr r+rrSrQr getRawHeadersrFrxrr}rus @r4 test_headerszParsingTests.test_headersIs         <0)Q?  //==fExP   " " 0 0 87G:L r3cgGfddtj}gd}|jdj||d\}|j |j j ddg|j |j j ddg|j |j j d d g|j |j j d d gy )aC Line folded headers are handled by L{HTTPChannel} by replacing each fold with a single space by the time they are made available to the L{Request}. Any leading whitespace in the folded lines of the header value is replaced with a single space, per: A server that receives an obs-fold in a request message ... MUST ... replace each received obs-fold with one or more SP octets prior to interpreting the field value or forwarding the message downstream. See RFC 7230 section 3.2.4. ceZdZfdZy)5ParsingTests.test_headersMultiline..MyRequestcHj||jyr7rrts r4rGz=ParsingTests.test_headersMultiline..MyRequest.processvrr3Nr~rwsr4rxrurr3rx) rs nospace: s nospace s space:spaces spacesspaces: spacess spacess spacesstab: ts as br3r3rlrsnospacesspaces space spacespacessspaces spaces spacesstabst a bNrrs @r4test_headersMultilinez"ParsingTests.test_headersMultilinees       <0)Q?    " " 0 0 < L    " " 0 0 :      " " 0 0 ; $ %    " " 0 0 8 J r3cLgGfddtj}gd}|jdj||d\}|j |j j ddg|j |j j dd g|j |j j d d g|j |j j d d g|j |j j ddgy)z Leading and trailing space and tab characters are stripped from headers. Other forms of whitespace are preserved. See RFC 7230 section 3.2.3 and 3.2.4. ceZdZfdZy):ParsingTests.test_headerStripWhitespace..MyRequestcHj||jyr7rrts r4rGzBParsingTests.test_headerStripWhitespace..MyRequest.processrr3Nr~rwsr4rxrrr3rx)rs!spaces: spaces were stripped stabs: tabs were stripped s5spaces-and-tabs: spaces and tabs were stripped s*line-tab: vertical tab was preserved s(form-feed: form feed was preserved r3r3rlrrsspaces were strippedstabsstabs were strippedsspaces-and-tabssspaces and tabs were strippedsline-tabs vertical tab was preserved s form-feeds form feed was preserved Nrrs @r4test_headerStripWhitespacez'ParsingTests.test_headerStripWhitespaces        <0)Q?    " " 0 0 ; $ %    " " 0 0 9 " #    " " 0 01C D - .    " " 0 0 = / 0    " " 0 0 > - . r3cdg}ttjjdzD]}|j t |d!|j ddg|j|y)z C{HTTPChannel} enforces a limit of C{HTTPChannel.maxHeaders} on the number of headers received per request. rrz: foor3N)rLr r maxHeadersr8rextendr)rFrrRs r4test_tooManyHeadersz ParsingTests.test_tooManyHeaderssj ** t''22Q67 .MyRequestcHj||jyr7rrts r4rGzBParsingTests.test_headerLimitPerRequest..MyRequest.process"rr3Nr~rwsr4rxr!rr3rxrr*)GET / HTTP/1.1rr3r3rsBar: bazr3r3rlrrrbazhHTTP/1.1 200 OK Transfer-Encoding: chunked 0 HTTP/1.1 200 OK Transfer-Encoding: chunked 0 N) r r+patchrrrSrQrqrr)rFrxrrfirstsecondrus @r4test_headerLimitPerRequestz'ParsingTests.test_headerLimitPerRequests      4##\15  //%**\":IqI# 0&9 ))&16:     # # %  r3cgGfddtj}tj}d|_d}|j |||d}|j g|j |j jdy) z Enforces a limit of C{HTTPChannel.totalHeadersSize} on the size of headers received per request starting from initial command line. ceZdZfdZy)@ParsingTests.test_headersTooBigInitialCommand..MyRequestcHj||jyr7rrts r4rGzHParsingTests.test_headersTooBigInitialCommand..MyRequest.processMrr3Nr~rwsr4rxrLrr3rxrs"GET /path/longer/than/10 HTTP/1.1 FrirrrrNr r+rtotalHeadersSizerrQrrrFrxrrirus @r4 test_headersTooBigInitialCommandz-ParsingTests.test_headersTooBigInitialCommandDs      ""$#% < //#$ "  B' **0024WXr3cgGfddtj}tj}d|_d}|j |||d}|j g|j |j jdy) z Enforces a limit of C{HTTPChannel.totalHeadersSize} on the size of headers received per request counting first line and total headers. ceZdZfdZy)>ParsingTests.test_headersTooBigOtherHeaders..MyRequestcHj||jyr7rrts r4rGzFParsingTests.test_headersTooBigOtherHeaders..MyRequest.processhrr3Nr~rwsr4rxrgrr3rx(s5GET /less/than/40 HTTP/1.1 Some-Header: less-than-40 FrrNrrs @r4test_headersTooBigOtherHeadersz+ParsingTests.test_headersTooBigOtherHeaders_s      ""$#% T //#$ "  B' **0024WXr3cGddtj}tj}d|_||_d}|j ||d}|j |jjdy) z Enforces total size of headers per individual request and counter is reset at the end of each request. ceZdZdZy)@ParsingTests.test_headersTooBigPerRequest..SimpleRequestc$|jyr7)rzrEs r4rGzHParsingTests.test_headersTooBigPerRequest..SimpleRequest.processs  r3Nr~r2r3r4 SimpleRequestrs r3rrsZGET / HTTP/1.1 Some-Header: total-less-than-60 GET / HTTP/1.1 Some-Header: less-than-60 F)rirrrN) r r+rrrrrQrr)rFrrris r4test_headersTooBigPerRequestz)ParsingTests.test_headersTooBigPerRequestzs  DLL ""$#% !.  //#We"      # # %  r3cd}i|Gfddtj}|j|||jddddy) z3 Test cookies parsing and reading. sKGET / HTTP/1.0 Cookie: rabbit="eat carrot"; ninja=secret; spam="hey 1=1!" ceZdZfdZy)+ParsingTests.testCookies..MyRequestcjdD]}|j||<d_|jy)NsrabbitsninjasspamT) getCookierrz)rFnamecookiestestcases r4rGz3ParsingTests.testCookies..MyRequest.processs5:9D$(NN4$8GDM9&*# r3Nr~)rrsr4rxrs r3rxs "eat carrot"ssecrets "hey 1=1!"rNr r+rrQ)rFrirxrrs @@r4 testCookieszParsingTests.testCookiessQ      Y/  '9} U r3cd}gg|Gfddtj}|j|||jdg|jdgdgddggy) NsJGET /?key=value&multiple=two+words&multiple=more%20words&empty= HTTP/1.0 ceZdZfdZy)'ParsingTests.testGET..MyRequestcj|jj|jd|jd|jdgd_|j yNskeysemptysmultipleT)r8rvrr8rrz)rFr8rvrs r4rGz/ParsingTests.testGET..MyRequest.processsW dkk* YYv& ((;TYY{=ST'+# r3Nr~)r8rvrsr4rxrs r3rxrvaluer3 two words more wordsr)rFrirxr8rvrs @@@r4testGETzParsingTests.testGETsr       Y/ &*  SEL-3PQRr3cd}ggg|Gfddtj}|j|||jdg|jdg|jdgdggy) z While only a single '?' is allowed in an URL, several other servers allow several and pass all after the first through as part of the query arguments. Test that we emulate this behavior. s"GET /foo?bar=?&baz=quux HTTP/1.0 ceZdZfdZy)6ParsingTests.test_extraQuestionMark..MyRequestcj|jj|jj|jd|jdgd_|j y)NrrT)r8rvpathrr8rrz)rFr8rvrrs r4rGz>ParsingTests.test_extraQuestionMark..MyRequest.processsW dkk* DII& TYYv. &0ABC&*# r3Nr~)r8rvrrsr4rxrs   r3rxrs/foo?rNr)rFrirxr8rvrrs @@@@r4test_extraQuestionMarkz#ParsingTests.test_extraQuestionMarks >       Y/ &* y)  23r3cBd}tdt||fz}ggg|Gfddtj}|j |||j dg|j dgdgdd gg|j t|gy ) a] The request body of a I{POST} request with a I{Content-Type} header of I{application/x-www-form-urlencoded} is parsed according to that content type and made available in the C{args} attribute of the request object. The original bytes of the request may still be read from the C{content} attribute. z9key=value&multiple=two+words&multiple=more%20words&empty=zVPOST / HTTP/1.0 Content-Length: %d Content-Type: application/x-www-form-urlencoded %sceZdZfdZy)4ParsingTests.test_formPOSTRequest..MyRequestc2j|jj|jd|jd|jdgj|jj d_|jyr)r8rvrr8rnrprrz)rFr8rnrvrs r4rGz.MyRequest.process sp dkk* YYv& ((;TYY{=STt||0023&*# r3Nr~)r8rnrvrsr4rxr  s   r3rxsPOSTrr3rrN)rrxr r+rrQ)rFqueryrirxr8rnrvrs @@@@r4test_formPOSTRequestz!ParsingTests.test_formPOSTRequestsL#  5z5!  "       Y/ '+  SEL-3PQR =#7"89r3cd}|j|tjd}|j|jj dy)zX When the multipart processing fails the client gets a 400 Bad Request. sPOST / HTTP/1.0 Content-Type: multipart/form-data; boundary=☃ Content-Length: 103 --☃ Content-Type: text/plain Content-Length: 999999999999999999999999999999999999999999999999999999999999999 Content-Transfer-Encoding: quoted-printable abasdfg --☃-- FrrN)rr r+rQrr)rFr2rs r4test_multipartProcessingFailurez,ParsingTests.test_multipartProcessingFailure sC //#t||U/C **0024WXr3cgGfddtj}d}|j||d}|j|jj d|jdj iy) zS When the multipart does not contain a header is should be skipped ceZdZfdZy)JParsingTests.test_multipartEmptyHeaderProcessingFailure..MyRequestcjj||jd|jyrrrsrts r4rGzRParsingTests.test_multipartEmptyHeaderProcessingFailure..MyRequest.process2 rvr3Nr~rwsr4rxr1 ryr3rxsrPOST / HTTP/1.0 Content-Type: multipart/form-data; boundary=AaBb1313 Content-Length: 14 --AaBb1313 --AaBb1313-- FrrzrN)r r+rrQrrr8r}s @r4*test_multipartEmptyHeaderProcessingFailurez7ParsingTests.test_multipartEmptyHeaderProcessingFailure+ sq    //#y%/@ **0024RS 1**B/r3c:gGfddtj}d}|j||d}|j|jj d|jt d|jdjd d giy ) z If the request has a Content-Type of C{multipart/form-data}, and the form data is parseable, the form arguments will be added to the request's args. ceZdZfdZy)6ParsingTests.test_multipartFormData..MyRequestcjj||jd|jyrrrsrts r4rGz>ParsingTests.test_multipartFormData..MyRequest.processO rvr3Nr~rwsr4rxrN ryr3rxsPOST / HTTP/1.0 Content-Type: multipart/form-data; boundary=AaB03x Content-Length: 149 --AaB03x Content-Type: text/plain Content-Disposition: form-data; name="text" Content-Transfer-Encoding: quoted-printable abasdfg --AaB03x-- Frrzr*rr{r|N)r r+rrQrrrxr8r}s @r4r~z#ParsingTests.test_multipartFormDataF s      //#y%/@ **0024RS Y+ 1**Wzl,CDr3c gGfddtj}d}dtt|j ddzdz}|j |j d|z|d }|j|jjd |jtd |jd jddgiy)z If the request has a Content-Type of C{multipart/form-data}, and the form data is parseable and contains files, the file portions will be added to the request's args. ceZdZfdZy)6ParsingTests.test_multipartFileData..MyRequestcjj||jd|jyrrrsrts r4rGz>ParsingTests.test_multipartFileData..MyRequest.processo rvr3Nr~rwsr4rxrn ryr3rxs-----------------------------738837029596785559389649595 Content-Disposition: form-data; name="uploadedfile"; filename="test" Content-Type: application/octet-stream abasdfg -----------------------------738837029596785559389649595-- zPOST / HTTP/1.0 Content-Type: multipart/form-data; boundary=---------------------------738837029596785559389649595 Content-Length: rlrz asciiFrrzr*rs uploadedfiler|N) r r+rrrxrhrrsrQrrr8)rFrxrr2rrus @r4test_multipartFileDataz#ParsingTests.test_multipartFileDataf s       #dll5'234  5    //#**W"5".MyRequestcj|jj|jjt|_j|jj|j j|j jd_|jyr:) r8rnrprrvrr_transferDecoderrrz)rFrnrrvrrs r4rGz.MyRequest.process s~t||,t||0023 'y  dkk* DII&t||<<=&*# r3Nr~)rnrrvrrsr4rxr$ s   r3rxrr*sHello, spam,eggs spam spamr/N)r r+r addCleanupcloser+rQ)rFrirxrnrrvrrs @@@@@r4test_chunkedEncodingz!ParsingTests.test_chunkedEncoding s       Y/  (()#D'!*5 %BC &* v& 4&)r3c.d}gGfddtj}|j||d}|jd|j |j j d|j|j jy) z If a request uses the I{chunked} transfer encoding, but provides an invalid chunk length value, the request fails with a 400 error. sGET / HTTP/1.1 Content-Type: text/plain Transfer-Encoding: chunked MALFORMED_LINE_THIS_SHOULD_BE_'6' Hello, 14 spam,eggs spam spam 0 ceZdZfdZy)=ParsingTests.test_malformedChunkedEncoding..MyRequestc(jdyr:r8)rFrs r4rGzEParsingTests.test_malformedChunkedEncoding..MyRequest.process s!!$'r3Nr~rsr4rxr- s (r3rxFrzRequest.process calledrN) r r+rrrQrrrr)rFrirxrrs @r4test_malformedChunkedEncodingz*ParsingTests.test_malformedChunkedEncoding s    (  ( //+y%/H %=> **0024WX ))778r3c: tj|t}g G fddtj}d}d}t j dj||f}d|zdz}|jt dd |j||d  j}|jd |j|jd t||d }|d }|j|j t"|j%t"y)z A L{Request} that throws an exception processing basic authorization logs an error and uses an empty username and password. ceZdZfdZy)5ParsingTests.test_basicAuthException..Requestcr|j|jf|_j|yr7rrs r4rGz=ParsingTests.test_basicAuthException..Request.process rr3Nr~rsr4r+r3 rr3r+rrrrr b64decodecgSr7r2)rs r4rz6ParsingTests.test_basicAuthException.. s"r3r)r3r3r* log_failureN)rrrr r+rrrSrrrrQrrrxassertIsInstancerAttributeErrorflushLoggedErrors) rFrr+rrrrr2rrs @r4test_basicAuthExceptionz$ParsingTests.test_basicAuthException s +<r?r@r3r3r=r@r3r3NrrEs r41test_duplicateContentLengthsWithPipelinedRequestsz>ParsingTests.test_duplicateContentLengthsWithPipelinedRequests9  ""  r3c*|jgdy)z A request that includes both C{content-length} and C{transfer-encoding} headers fails with a 400 response without calling L{Request.process}. )r=rdr?r@r3r3NrrEs r4%test_contentLengthAndTransferEncodingz2ParsingTests.test_contentLengthAndTransferEncodingN s ""  r3c*|jgdy)z Two pipelined requests, the first of which includes both C{content-length} and C{transfer-encoding} headers, triggers a 400 response without calling L{Request.process}. ) r=rdr?r@r3r3r=r@r3r3NrrEs r4:test_contentLengthAndTransferEncodingWithPipelinedRequestszGParsingTests.test_contentLengthAndTransferEncodingWithPipelinedRequests_ rKr3c*|jgdy)z A request whose C{transfer-encoding} header includes a value other than C{chunked} or C{identity} fails with a 400 response without calling L{Request.process}. )r=sTransfer-Encoding: unknownr@r3r3NrrEs r4test_unknownTransferEncodingz)ParsingTests.test_unknownTransferEncodingt s ""  r3cgGfddtj}d}|j||d}|jdg|j|jj dy)z A request with a valid C{content-length} and a C{transfer-encoding} whose value is C{identity} succeeds. ceZdZdZfdZy)EParsingTests.test_transferEncodingIdentity..SuccessfulRequestFcj|jj|jdd|j y)Nrk0)r8rnrprtrz)rFrs r4rGzMParsingTests.test_transferEncodingIdentity..SuccessfulRequest.process s4 DLL--/00$7 r3N)r.r/r0rurG)rsr4SuccessfulRequestrT s I r3rWsTGET / HTTP/1.1 Host: host.invalid Content-Length: 2 Transfer-Encoding: identity ok Fsoks&HTTP/1.1 200 OK Content-Length: 0 N)r r+rrQrr)rFrWr}rrs @r4test_transferEncodingIdentityz*ParsingTests.test_transferEncodingIdentity sk    //'+.urls s}- Q-QD +Q$2QD#/'+d{]3t95M'M&0&$c31O&P PQQQ Qs A5Ac|}|r|jd}t|}t|jtr|jj d|j j d|jj d|jj d|jj d|jj df}nD|j|j |j|j|j|jf}tj|\}}}}} } j||||| | f| j|t j|t j|t j|t j| t j| ty)z Verify that C{url} is parsed into the same objects by both L{http.urlparse} and L{urlparse}. r zutf-8N)decoder isinstancer^rrrsnetlocrparamsrfragmentr rQr8r) urlrcurlToStandardImplementationstandardResultrr^rerrfrrgrFs r4assertSameParsingz.assertSameParsing s +. '.1jj.A+ &&ABN.//5#))009"))009"''..w7"))009"((//8"++227; #))"))"''"))"(("++ =AMM#d=Z?d>Z@d?ZAd@ZBdAZCdBZDdCZEdDZFdEZGdFZHdGZIdHZJdIZKdJZLdKZMyL)M RequestTestsz# Tests for L{http.Request} ctjtd}t||j ddg|j t||ddt ||ddi|j tt||jddgfgt ||tj|j t||iy)a0 Verify that each of two different attributes which are associated with the same state properly reflect changes made through the other. This is used to test that the C{headers}/C{responseHeaders} and C{received_headers}/C{requestHeaders} pairs interact properly. Fr^r_rrraN) r r+r&getattrrrQsetattrrrr!Headers)rFoldNamenewNamer2s r4_compatHeadersTestzRequestTests._compatHeadersTest sll<>51W++GhZ@ g.w7BWvv./  g&779 :fvh=O51 ((8*= w/:r3ctjtdfd}|dd|dd|dd|dd|dd|d d |d d |d d |ddy)z L{http.Request.getRequestHostname} returns the hostname portion of the request, based on the C{Host:} header. Fcjjd|gjj|y)Nhost)rrrQgetRequestHostname)rk expectedHostr2rFs r4checkz3RequestTests.test_getRequestHostname..check= s4    , ,Wvh ?   S335| Dr3r]sexample.com:8443s 192.168.1.1s192.168.1.1:19289s[2607:f0d0:1002:51::4]s2607:f0d0:1002:51::4s)[2607:f0d0:1002:0051:0000:0000:0000:0004]s'2607:f0d0:1002:0051:0000:0000:0000:0004s[::1]s::1s [::1]:8080s[2607:f0d0:1002:51::4]:9443N)r r+r&)rFrr2s` @r4test_getRequestHostnamez$RequestTests.test_getRequestHostname6 s ll<>51 E nn- !>2 nn- "N3 ')@A 8 6  h mV$ ,.EFr3ctjtd}|jj dddg|j |j ddy)z When there are multiple values for a single request header, L{http.Request.getHeader} returns the last value. Fr^r_pandaNrrs r4test_getHeaderReceivedMultiplesz,RequestTests.test_getHeaderReceivedMultiplesN sJ ll<>51 ((8X2FG w/:r3ctjtd}|j|j ddy)z L{http.Request.getHeader} returns L{None} when asked for the value of a request header which is not present. Fr^N)r r+r&rQrqrs r4test_getHeaderNotFoundz#RequestTests.test_getHeaderNotFoundW s/ ll<>51 w/6r3ctjtd}|jj ddg|j |j ddiy)z L{http.Request.getAllheaders} returns a C{dict} mapping all request header names to their corresponding values. Fr^r_Nr r+r&rrrQ getAllHeadersrs r4test_getAllHeaderszRequestTests.test_getAllHeaders_ sL ll<>51 ((8*= **,w.ABr3ctjtd}|j|j iy)zq L{http.Request.getAllHeaders} returns an empty C{dict} if there are no request headers. FN)r r+r&rQrrs r4test_getAllHeadersNoHeadersz(RequestTests.test_getAllHeadersNoHeadersh s/ ll<>51 **,b1r3ctjtd}|jj dddg|j |j ddiy)z When there are multiple values for a single request header, L{http.Request.getAllHeaders} returns only the last value. Fr^r_rNrrs r4!test_getAllHeadersMultipleHeadersz.RequestTests.test_getAllHeadersMultipleHeadersp sO ll<>51 ((8X2FG **,w.ABr3ct}tj|d}|jd|j d|j |j jjjddy)z~ L{http.Request.setResponseCode} takes a status code and causes it to be used as the response status. Fr3rs (no clientproto yet) 201 CreatedN r&r r+rCryrQrwrittengetvaluerrFrr2s r4test_setResponseCodez!RequestTests.test_setResponseCodey sk .ll7E* C  #     % % . . 0 ; ; =a @ / r3ct}tj|d}|jdd|j d|j |j jjjddy)z L{http.Request.setResponseCode} takes a status code and a message and causes them to be used as the response status. Fshappily acceptedr3rs)(no clientproto yet) 202 happily acceptedNrrs r4test_setResponseCodeAndMessagez+RequestTests.test_setResponseCodeAndMessage sn .ll7E* C!45 #     % % . . 0 ; ; =a @ 8 r3ct}tj|d}|jt|j ddy)z L{http.Request.setResponseCode} accepts C{bytes} for the message parameter and raises L{TypeError} if passed anything else. Frznot happily acceptedN)r&r r+rYrnrCrs r4&test_setResponseCodeAndMessageNotBytesz3RequestTests.test_setResponseCodeAndMessageNotBytes s6 .ll7E* )S%8%8#?UVr3ctjtd}|jd|j t |jdy)z L{http.Request.setResponseCode} accepts C{int} for the code parameter and raises L{TypeError} if passed anything else. Fr*1N)r r+r&rCrYrnrs r4#test_setResponseCodeAcceptsIntegersz0RequestTests.test_setResponseCodeAcceptsIntegers s< ll<>51 A )S%8%8#>r3cbtjtd}|jdy)z` L{http.Request.setResponseCode} accepts L{int} for the code parameter. Fr*N)r r+r&rCrs r4'test_setResponseCodeAcceptsLongIntegersz4RequestTests.test_setResponseCodeAcceptsLongIntegers s$ ll<>51 Ar3ctjtd}|jd|j |j dy)z When no previous value was set and no 'if-modified-since' value was requested, L{http.Request.setLastModified} takes a timestamp in seconds since the epoch and sets the request's lastModified attribute. F*Nr r+r&setLastModifiedrQ lastModifiedrs r4test_setLastModifiedNeverSetz)RequestTests.test_setLastModifiedNeverSet s: ll<>51 B ))2.r3ctjtd}|jd|jd|j |j dy)z If the supplied timestamp is later than the lastModified attribute's value, L{http.Request.setLastModified} updates the lastModifed attribute. Frr*Nrrs r4test_setLastModifiedUpdatez'RequestTests.test_setLastModifiedUpdate sH ll<>51 A A ))1-r3ctjtd}|jd|jd|j |j dy)z If the supplied timestamp occurs earlier than the current lastModified attribute, L{http.Request.setLastModified} ignores it. Fr*rNrrs r4test_setLastModifiedIgnorez'RequestTests.test_setLastModifiedIgnore sH ll<>51 A A ))1-r3ctjtd}|jj t ddg|j d}|j|tjy)z If the resource is older than the if-modified-since date in the request header, L{http.Request.setLastModified} returns L{http.CACHED}. Fif-modified-sinces02 Jan 1970 00:00:00 GMTrN r r+r&rrrrrQCACHEDrFr2rYs r4test_setLastModifiedCachedz'RequestTests.test_setLastModifiedCached s_ ll<>51 (( - .1L0M $$R( -r3ctjtd}|jj t ddg|j d}|j|dy)z If the resource is newer than the if-modified-since date in the request header, L{http.Request.setLastModified} returns None Frs01 Jan 1970 00:00:00 GMT@BNr r+r&rrrrrQrs r4test_setLastModifiedNotCachedz*RequestTests.test_setLastModifiedNotCached s[ ll<>51 (( - .1L0M $$W- &r3ctjtd}|jj t ddg|j d|j d}|j|dy)z When L{http.Request.setLastModified} is called multiple times, the highest supplied value is honored. If that value is higher than the if-modified-since date in the request header, the method returns None. Frs01 Jan 1970 00:00:01 GMTrrNrrs r4"test_setLastModifiedTwiceNotCachedz/RequestTests.test_setLastModifiedTwiceNotCached si ll<>51 (( - .1L0M  G$$$Q' &r3ctjtd}|jj t ddg|j d|j d}|j|tjy)a When L{http.Request.setLastModified} is called multiple times, the highest supplied value is honored. If that value is lower than the if-modified-since date in the request header, the method returns L{http.CACHED}. Frs01 Jan 1999 00:00:01 GMTr*rNrrs r4test_setLastModifiedTwiceCachedz,RequestTests.test_setLastModifiedTwiceCached smll<>51 (( - .1L0M  A$$Q' -r3ctjtd}|jdd|j |j j ddgy) L{http.Request.setHost} sets the value of the host request header. The port should not be added because it is the default. Fr]PrNr r+r&setHostrQrrrs r4 test_setHostzRequestTests.test_setHost sH ll<>51 NB' ++99'B^DTUr3ct}tj|_tj|d}|j dd|j |jjddgy)rFr]irN r&r/rr r+rrQrrrFrr2s r4test_setHostSSLzRequestTests.test_setHostSSL s] N"&&( ll1e$ NC( ++99'B^DTUr3ctjtd}|jdd|j |j j ddgyz L{http.Request.setHost} sets the value of the host request header. The port should be added because it is not the default. Fr]Qrsexample.com:81Nrrs r4test_setHostNonDefaultPortz'RequestTests.test_setHostNonDefaultPort% sI ll<>51 NB' ++99'BEVDWXr3ct}tj|_tj|d}|j dd|j |jjddgyrrrs r4test_setHostSSLNonDefaultPortz*RequestTests.test_setHostSSLNonDefaultPort. s^ N"&&( ll1e$ NB' ++99'BEVDWXr3ctjtd}|jdd|j |j j ddgy)zX L{http.Request.setHeader} sets the value of the given response header. Fr^r_N)r r+r&rtrQrrrs r4test_setHeaderzRequestTests.test_setHeader9 sGll<>51 gx( ,,::7ChZPr3ct}tj|d}|j|i||j |j d||j d|jjjjd}|Dcgc]}|jds|}}|j t|d|j |dd|zycc}w) z Call L{http.Request.addCookie} with C{*args} and C{**kwargs}, and check that the cookie value is equal to C{expectedCookieValue}. Frr3rs Set-Cookier*s Set-Cookie: N) r&r r+ addCookierQrryrrrr startswithrx) rFexpectedCookieValuer8r9rr2 writtenLinesraddCookieLiness r4 _checkCookiezRequestTests._checkCookieA s .ll7E* t&v& Q)<= #((0099;AA'J &2QQ\\-5P!QQ ^,a0 *O>Q,QRRs C+1C+c.d}|j|ddy)z L{http.Request.addCookie} adds a new cookie to be sent with the response, and can be called with just a key and a value. L{unicode} arguments are encoded using UTF-8. foo=barfoobarNrrFrs r4)test_addCookieWithMinimumArgumentsUnicodez6RequestTests.test_addCookieWithMinimumArgumentsUnicodeT s ) -ued}|j|dddddddd d y ) z L{http.Request.addCookie} adds a new cookie to be sent with the response. L{unicode} arguments are encoded using UTF-8. }foo=bar; Expires=Fri, 31 Dec 9999 23:59:59 GMT; Domain=.example.com; Path=/; Max-Age=31536000; Comment=test; Secure; HttpOnlyrrzFri, 31 Dec 9999 23:59:59 GMTz .example.com/31536000testTexpiresdomainrmax_agecommentsecurehttpOnlyNrrs r4%test_addCookieWithAllArgumentsUnicodez2RequestTests.test_addCookieWithAllArgumentsUnicode^ s?  .     3!  r3c.d}|j|ddy)z L{http.Request.addCookie} adds a new cookie to be sent with the response, and can be called with just a key and a value. L{bytes} arguments are not decoded. rrrNrrs r4'test_addCookieWithMinimumArgumentsBytesz4RequestTests.test_addCookieWithMinimumArgumentsBytesv s ) -vv>r3c >d}|j|dddddddd d y ) z L{http.Request.addCookie} adds a new cookie to be sent with the response. L{bytes} arguments are not decoded. rrrsFri, 31 Dec 9999 23:59:59 GMTs .example.comr's31536000r^TrNrrs r4#test_addCookieWithAllArgumentsBytesz0RequestTests.test_addCookieWithAllArgumentsBytes s?  .     4"  r3c Jd}gd}ttttzt t g}ddgddgg}|D]a\}}|j ||||||D]=\}}dj||||||g}|j |||fi||i?cy)zq L{http.Request.addCookie} replaces linear whitespace and semicolons with single spaces. c(dj||gS)N=)rS)rrs r4 cookieValuez.cookieValue s99c5\* *r3))rsExpires)rsDomain)rsPath)rsMax-Age)rsCommentzFoo; barsFoo barsFoo; bars; N)rzipr)r'rr(rrS) rFr argumentsinputsAndOutputs inputValue outputValueargument parameterrs r4test_addCookieSanitizationz'RequestTests.test_addCookieSanitization s  +  .1PP~&'   % + &  (8  #J   K5z: (1 #) ::#K=#I{; "!!j*9A:8N  r3c|jdddd|jdddd|jdddd|jt|jd ddd y ) zL L{http.Request.setCookie} supports a C{sameSite} argument. sfoo=bar; SameSite=laxrrlax)sameSiteLaxsfoo=bar; SameSite=strictstrictr3z anything-elseN)rrYrZrEs r4test_addCookieSameSitez#RequestTests.test_addCookieSameSite sx 2FFUS 2FFUS  '(    ))3  r3c4t}tj|d}t}||_|j dd|_|jjddg|jd|j|jdgy) z For an HTTP 1.0 request, L{http.Request.write} sends an HTTP 1.0 Response-Line and whatever response headers are set. FrArtr^r_r`)rrcr`N r&r r+rrrCrwrrryrrrFrr2res r4test_firstWritezRequestTests.test_firstWrite s .ll7E*!! C % ))'H:> ( !! KKMJK r3cVt}tj|d}t}||_|j dd|_|jjddg|jd|jd|j|jdgy ) z For an HTTP 1.1 request, L{http.Request.write} sends an HTTP 1.1 Response-Line, whatever response headers are set, and uses chunked encoding for the response body. FrArr^r_r`rarbNrrs r4test_firstWriteHTTP11Chunkedz)RequestTests.test_firstWriteHTTP11Chunked s .ll7E*!! C % ))'H:> ( ) !! KKM  r3cBt}tj|d}t}||_|j dd|_d|_|jjddg|jd|j|jdgy ) z For an HTTP 1.0 request for a resource with a known last modified time, L{http.Request.write} sends an HTTP Response-Line, whatever response headers are set, and a last-modified header with that time. FrArtrr^r_r`)rrc,Last-Modified: Thu, 01 Jan 1970 00:00:00 GMTr`N) r&r r+rrrCrwrrrryrrrs r4test_firstWriteLastModifiedz(RequestTests.test_firstWriteLastModified s .ll7E*!! C % ))'H:> ( !! KKM  r3ctj|t}t}t j |d}t }||_|jdd|_ d|_ |jjddg|jd|j|jdg|j!d t#||d }|j!d |d y )z If the last-modified header already exists in the L{http.Request} response headers, the lastModified attribute is ignored and a message is logged. FrArtiʚ;s last-modifiedsThu, 01 Jan 1970 00:00:00 GMTr`)rrr`r*rzPWarning: last-modified specified both in header list and lastModified attribute.rN)rrrr&r r+rrrCrwrrrryrrrrx)rFrrr2rers r4test_lastModifiedAlreadyWrittenz,RequestTests.test_lastModifiedAlreadyWritten" s +<51 --r2r3ctjtd}|jj ddg|j |j |jdddy)z L{http.Request.parseCookies} extracts cookies from C{requestHeaders} and adds them to C{received_cookies}. Fcookiestest="lemur"; test2="panda""lemur""panda"r^stest2Nr r+r&rr parseCookiesrQrrs r4test_parseCookieszRequestTests.test_parseCookiesP sZ ll<>51 ((5S4TU    J*"M r3ctjtd}|jj dddg|j |j |jdddy) zh L{http.Request.parseCookies} can extract cookies from multiple Cookie headers. Frs test="lemur"s test2="panda"rrrNr rs r4 test_parseCookiesMultipleHeadersz-RequestTests.test_parseCookiesMultipleHeaders\ s\ ll<>51 ((_FV4WX    J*"M r3ctjtd}|j|j |j iy)zj L{http.Request.parseCookies} can be called on a request without a cookie header. FN)r r+r&r!rQrrs r4test_parseCookiesNoCookiez&RequestTests.test_parseCookiesNoCookieh s8 ll<>51  --r2r3ctjtd}|jj dg|j |j |jiy)zn L{http.Request.parseCookies} can be called on a request with an empty cookie header. FrNr rs r4test_parseCookiesEmptyCookiez)RequestTests.test_parseCookiesEmptyCookieq sN ll<>51 ((B7  --r2r3ctjtd}|jj ddg|j |j |jiy)z` L{http.Request.parseCookies} ignores cookies which don't have a value. Frsfoo; bar; baz;Nr rs r4 test_parseCookiesIgnoreValuelessz-RequestTests.test_parseCookiesIgnoreValueless{ sR ll<>51 ((5F4GH  --r2r3ctjtd}|jj ddg|j |j |jddiy)zR L{http.Request.parseCookies} parses cookies with an empty value. Frsfoo=rr3Nr rs r4test_parseCookiesEmptyValuez(RequestTests.test_parseCookiesEmptyValue sTll<>51 ((WI>  --}=r3ctjtd}|jj ddg|j |j |jddiy)zf L{http.Request.parseCookies} leaves trailing whitespace in the cookie value. Frsfoo=bar rsbar Nr rs r4!test_parseCookiesRetainRightSpacez.RequestTests.test_parseCookiesRetainRightSpace sU ll<>51 (([MB  --/@Ar3ctjtd}|jj ddg|j |j |jddiy)zc L{http.Request.parseCookies} strips leading whitespace in the cookie key. Frs foo=barrrNr rs r4test_parseCookiesStripLeftSpacez,RequestTests.test_parseCookiesStripLeftSpace sU ll<>51 (([MB  --/?@r3ctjtd}|jj ddg|j |j |jdddy)zr L{http.Request.parseCookies} parses valid cookies set before or after malformed cookies. Frs012345; test="lemur"; 12345; test2="panda"; 12345rrrNr rs r4-test_parseCookiesContinueAfterMalformedCookiez:RequestTests.test_parseCookiesContinueAfterMalformedCookie s_ ll<>51 (( KL     J*"M r3cPtjtd}|jd|j}|j d|j ttd|j|j|j|jdy)z L{http.Request.connectionLost} closes L{Request.content} and drops the reference to the L{HTTPChannel} to assist with garbage collection. Frr,FinishedN) r r+r& gotLengthrnhandleContentChunkrrrrclosedrr)rFr2rns r4test_connectionLostz RequestTests.test_connectionLost s} ll<>51 b++ x( 7>*#=>? ' S[[$/r3ctjtd}|jt d|j t |jt dy)zv Calling L{Request.registerProducer} when a producer is already registered raises ValueError. FTN)r r+r&rDrrYrZrs r4test_registerProducerTwiceFailsz,RequestTests.test_registerProducerTwiceFails sD ll<>51 ]_d3 *c&:&:MOTRr3ctjtd}t}|j |d|j |dfg|j jy)z Calling L{Request.registerProducer} with an IPushProducer when the request is not queued registers the producer as a push producer on the request's transport. FTNr r+r&rrDrQr producersrFr2rls r47test_registerProducerWhenNotQueuedRegistersPushProducerzDRequestTests.test_registerProducerWhenNotQueuedRegistersPushProducer sO ll<>51 ? Xt, 8T*+S]]-D-DEr3ctjtd}t}|j |d|j |dfg|j jy)z Calling L{Request.registerProducer} with an IPullProducer when the request is not queued registers the producer as a pull producer on the request's transport. FNr<r>s r47test_registerProducerWhenNotQueuedRegistersPullProducerzDRequestTests.test_registerProducerWhenNotQueuedRegistersPullProducer sO ll<>51 ? Xu- 8U+,cmm.E.EFr3c t}tj|d}|j}|j t t d|j|jd|j|t S)z L{Request.connectionLost} triggers all finish notification Deferreds and cleans up per-request state. TzConnection doneN) r&r r+ notifyFinishrrrrr assertFailure)rFrr}rs r4test_connectionLostNotificationz,RequestTests.test_connectionLostNotification si N,,q$''')w~6G'HIJ W__d3!!(N;;r3ctjtd}|j}|j d|j |S)zO L{Request.finish} triggers all finish notification Deferreds. Fr*)r r+r&rCr5rzrFr}rs r4test_finishNotificationz$RequestTests.test_finishNotification sC,,|~u5'') !r3ctjtd}|j}|j d|j d|j |jt|j d|S)z Calling L{Request.write} after L{Request.finish} has been called results in a L{RuntimeError} being raised. Fr*foobar) r r+r&rCr5ryrzrYrrGs r4test_writeAfterFinishz"RequestTests.test_writeAfterFinish se ,,|~u5'') ! i  , yAr3ct}tj|d}|jt t d|j t|jy)z Calling L{Request.finish} after L{Request.connectionLost} has been called results in a L{RuntimeError} being raised. FThe end.N) r&r r+rrrrYrrzrs r4test_finishAfterConnectionLostz+RequestTests.test_finishAfterConnectionLost sG .ll7E* 7>*#=>? , 3r3ct}tj|d}|jt t d|j d|jt|jy)z Calling L{Request.write} after L{Request.connectionLost} has been called does not raise an exception. L{RuntimeError} will be raised when finish is called on the request. FrMrJN) r&r r+rrrryrYrrzrs r4test_writeAfterConnectionLostz*RequestTests.test_writeAfterConnectionLostsS .ll7E* 7>*#=>? ) , 3r3ctjtd}|jt |dt |fzy)z L{Request.__repr__} returns the class name, object address, and dummy-place holder values when used on a L{Request} which has not yet been initialized. FzZNr r+r&rQrepridrFr}s r4test_reprUninitializedz#RequestTests.test_reprUninitialized!s? ,,|~u5  M 035g;. A r3ctjtd}d|_d|_d|_|j t|dt|fzy)a L{Request.__repr__} returns, as a L{str}, the class name, object address, and the method, uri, and client protocol of the HTTP request it represents. The string is in the form:: Frtrrz>N) r r+r&rwrvrurQrSrTrUs r4test_reprInitializedz!RequestTests.test_reprInitialized.sT,,|~u5)!   M $')'{n 5 r3cGddtj}|td}|jt |dt |fzy)z Subclasses of L{Request} inherit a C{__repr__} implementation which includes the subclass's name in place of the string C{"Request"}. c eZdZy)1RequestTests.test_reprSubclass..OtherwiseN)r.r/r0r2r3r4 Otherwiser[Fs r3r\Fz\NrR)rFr\r}s r4test_reprSubclasszRequestTests.test_reprSubclass@sK    LNE2  M 035g;. A r3ctjtd}t|_|j t d|j|jd|j|jjfy)z L{Request.unregisterProducer} unregisters a non-queued non-streaming producer from the request and the request's transport. FNNN r r+r&rrrDrunregisterProducerrQrlrs r4,test_unregisterNonQueuedNonStreamingProducerz9RequestTests.test_unregisterNonQueuedNonStreamingProducerPsa ll<>51')  ]_e4    cmm6L6L'MNr3ctjtd}t|_|j t d|j|jd|j|jjfy)z L{Request.unregisterProducer} unregisters a non-queued streaming producer from the request and the request's transport. FTr_Nr`rs r4)test_unregisterNonQueuedStreamingProducerz6RequestTests.test_unregisterNonQueuedStreamingProducer[sa ll<>51')  ]_d3    cmm6L6L'MNr3ctj}d|_d|_d|_|j t |_|jd}ddg}t}|j||D]}|j||jjdj|jd|jj!y)zj L{http.Request.finish} will call the channel's factory to produce a log message. NsometimeTGET /path HTTP/1.1 rrssometime "GET /path HTTP/1.1")r rr _logDateTime_logDateTimeCall startFactoryrlogFilerrrrrrrzrrrFrprotovalrers r4test_finishProducesLogz#RequestTests.test_finishProducesLogfs ""$)#' !)%%d+(+6! U# "A   q ! " "))+ 68P8P8RSr3ct}tjd|}|j|j d}t }t ||}|j|jd|j||jd|jd|j|j|jd|j|jy)z L{HTTPChannel} timeouts whenever data from a request body is not delivered to it in time, even when it gets built from a L{HTTPFactory}. r)timeoutrNrrr)rr rrjrrrrQrrrrrrrrhs r4"test_requestBodyTimeoutFromFactoryz/RequestTests.test_requestBodyTimeoutFromFactorys ""3>((.#% *8U; ))3/ *MN b 001 a  //0r3c^tj}d|_d|_d|_|j t |_|jd}d|j_ ddg}t}|j||j|jd|D]}|j||jd|j|jd |jj dj#|j|jdy) z L{http.Request.finish} will notify the channel that it is finished, and will put the transport back in the producing state so that the reactor can close the connection. NrfTrrgrrsGET r)r rrrhrirjrrkrrrrrrQrrrrzrls r4test_finishCleansConnectionz(RequestTests.test_finishCleansConnections ""$)#' !)%%d+23/(+6! U# ,,k: "A   q ! " 7# ,,h7 "))+ ,,k:r3cttjtd}ttj|y)z L{http.Request} provides L{http._IDeprecatedHTTPChannelToRequestInterface}, which defines the interface used by L{http.HTTPChannel}. FN)r r+r&r)_IDeprecatedHTTPChannelToRequestInterfacers r46test_provides_IDeprecatedHTTPChannelToRequestInterfacezCRequestTests.test_provides_IDeprecatedHTTPChannelToRequestInterfaces& ll<>51TCCSIr3cdtjtd}|j||y)z7 A L{http.Request} is equal to itself. FNr r+r&rQrs r4test_eqzRequestTests.test_eqs&ll<>51 c"r3ctjtd}|j|tjtdy)zC A L{http.Request} is not equal to another object. FN)r r+r&assertNotEqualrs r4test_nezRequestTests.test_nes3ll<>51 Clne!DEr3cVtjtd}t|y)z0 A L{http.Request} is hashable. FN)r r+r&hashrs r4 test_hashablezRequestTests.test_hashablesll<>51 S r3cgGfdd}tjtd}|j|||j|gy)z A L{http.Request} on the left hand side of an equality comparison to an instance that is not a L{http.Request} hands the comparison off to that object's C{__eq__} implementation. c"eZdZdedeffd Zy)8RequestTests.test_eqWithNonRequest.._NotARequestotherreturnc(j|yr:r/rFreqCallss r4__eq__z?RequestTests.test_eqWithNonRequest.._NotARequest.__eq__u%r3N)r.r/r0objectboolrrsr4 _NotARequestr F t r3rFNryrFrr2rs @r4test_eqWithNonRequestz"RequestTests.test_eqWithNonRequestsL    ll<>51 ln- 3%(r3cgGfdd}tjtd}|j|||j |gy)z A L{http.Request} on the left hand side of an inequality comparison to an instance that is not a L{http.Request} hands the comparison off to that object's C{__ne__} implementation. c"eZdZdedeffd Zy)8RequestTests.test_neWithNonRequest.._NotARequestrrc(j|yr:r/rs r4__ne__z?RequestTests.test_neWithNonRequest.._NotARequest.__ne__rr3N)r.r/r0rrrrsr4rrrr3rFN)r r+r&r|rQrs @r4test_neWithNonRequestz"RequestTests.test_neWithNonRequestsL    ll<>51 C0 3%(r3c|tj|t}tjt d}|j td|j|jdt||d}|d}|j|jt|jty)zy A RuntimeError is logged if a producer is still registered when an L{http.Request} is finished. FTr*rr7N)rrrr r+r&rDrrzrrxr8rrr:)rFrr}rrs r4"test_finishProducerStillRegisteredz/RequestTests.test_finishProducerStillRegistereds +<BA  0*S F G <  4 4   $ O OT41,;>J#F)$)$ -=76:r3rc@eZdZdZdZddddZdZdZd Zd Z d Z y ) MultilineHeadersTestsa Tests to exercise handling of multiline headers by L{HTTPClient}. RFCs 1945 (HTTP 1.0) and 2616 (HTTP 1.1) state that HTTP message header fields can span multiple lines if each extra line is preceded by at least one space or horizontal tab. c d|_d|_y)zv Initialize variables used to verify that the header-processing functions are getting called. FN)handleHeaderCalledhandleEndHeadersCalledrEs r4rzMultilineHeadersTests.setUp6s #(&+#r310s line-0 line-1s line-2 line-3)rms X-Multilines X-Multiline2cPd|_|j||j|y)zE Dummy implementation of L{HTTPClient.handleHeader}. TN)rrQr)rFrrns r4ourHandleHeaderz%MultilineHeadersTests.ourHandleHeaderFs'#' d22378r3cd|_y)zI Dummy implementation of L{HTTPClient.handleEndHeaders}. TN)rrEs r4ourHandleEndHeadersz)MultilineHeadersTests.ourHandleEndHeadersMs '+#r3c t}|j|_|j|_|j d|j d|j |jd|j|j|j|j|j d|j|j|j|j|j|jdy)z A header isn't processed by L{HTTPClient.extractHeader} until it is confirmed in L{HTTPClient.lineReceived} that the header has been received completely. r|Content-Length: 10Nr3r) rqrrrrrxrr|rrrrrQrys r4test_extractHeaderz(MultilineHeadersTests.test_extractHeaderSs N--!55 ' ,- QXXt, 001 445 s //0 334 2&r3c|t}|j|_|j|_|j d|j d|j |j|j|j|j|jd|j|jdy)z An HTTP request with no headers will not cause any calls to L{handleHeader} but will cause L{handleEndHeaders} to be called on L{HTTPClient} subclasses. r|r3rtrvN) rqrrrrrxrrrrrQryrrys r4test_noHeadersz$MultilineHeadersTests.test_noHeadersjs N--!55 ' s 001 334 K0 6*r3ct}|j|_|j|_|j d|j d|j |j|j d|j d|j|j|j d|j d|j d|j|j|j|jd|j|jd |j|jd y ) z L{HTTPClient} parses multiline headers by buffering header lines until an empty line or a line that does not start with whitespace hits lineReceived, confirming that the header has been received completely. r|sX-Multiline: line-0s line-1sX-Multiline2: line-2s line-3rr3rtrvrN)rqrrrrrxrrrrrQryrr|rys r4test_multilineHeadersz+MultilineHeadersTests.test_multilineHeaders}s N--!55 ' -. 001 {# ./ //0 z" ,- s 334 K0 6* 2&r3N) r.r/r0r1rrrrrrrr2r3r4rr.s7,!))O 9+ '.+&'r3rceZdZdZdZdZy)Expect100ContinueServerTestsai Test that the HTTP server handles 'Expect: 100-continue' header correctly. The tests in this class all assume a simplistic behavior where user code cannot choose to deny a request. Once ticket #288 is implemented and user code can run before the body of a POST is processed this should be extended to support overriding this behavior. ct}tj}t|_|j ||j d|j d|j d|j d|j d|j|jd|j d|j|jdgy ) z HTTP/1.0 requests do not get 100-continue returned, even if 'Expect: 100-continue' is included (RFC 2616 10.1.1). sGET / HTTP/1.0 Host: www.example.com Content-Length: 3 Expect: 100-continue rr3r)rrrrr ''' 3 abc''' N) rr rrrrrrQrr)rFrrs r4 test_HTTP10z(Expect100ContinueServerTests.test_HTTP10s $% ""$!6y)239:5689W% *C0V$ !! OO   r3cft}tj}t|_|j ||j d|j d|j d|j d|j|jd|j d|j|jd|j d|j}|j|jd|tdd }|j|d gy ) a! If a HTTP/1.1 client sends a 'Expect: 100-continue' header, the server responds with a 100 response code before handling the request body, if any. The normal resource rendering code will then be called, which will send an additional response code. sGET / HTTP/1.1 rrrr3rsHTTP/1.1 100 Continue rN)rrrrrr) rr rrrrrrQrrrrxr)rFrrrs r4test_expect100ContinueHeaderz9Expect100ContinueServerTests.test_expect100ContinueHeaders $% ""$!6y)239:8956 *C0W% *,LMV$??$ ++,LMNC @ACD !!   r3N)r.r/r0r1rrr2r3r4rrs <& r3rc4|Dcic]}||| c}Scc}w)a Create a new dict containing only a subset of the items of an existing dict. @param keys: An iterable of the keys which will be added (with values from C{d}) to the result. @param d: The existing L{dict} from which to copy items. @return: The new L{dict} with keys given by C{keys} and values given by the corresponding values in C{d}. @rtype: L{dict} r2)keysrks r4subrs " "AqtG "" "s ceZdZdZdZdZy) DeprecatedRequestAttributesTestszI Tests for deprecated attributes of L{twisted.web.http.Request}. c tjttjddd}|j d|j ddd|j|j|jg }|jd t||jtd d td dg|dy)zg L{Request.getClientIP} is deprecated in favor of L{Request.getClientAddress}. r5ri90rrrr'roffendingFunctionsr*zjtwisted.web.http.Request.getClientIP was deprecated in Twisted 18.4.0; please use getClientAddress insteadcategoryrzrrzN)r r+r&rrr5requestReceivedr flushWarningstest_getClientIPrQrxDeprecationWarningr)rFr}warningss r4rz1DeprecatedRequestAttributesTests.test_getClientIPs ,, g11%eL M  !k:%%$:O:O9P%Q CM* .M  Y'! 5 r3c"t}tj|}|j|j |j g}|j dt||j tddtddg|dy) zs L{Request.noLongerQueued} is deprecated, as we no longer process requests simultaneously. rr*zHtwisted.web.http.Request.noLongerQueued was deprecated in Twisted 16.3.0rrrzrN) r&r r+noLongerQueuedrtest_noLongerQueuedrQrxrr)rFrr}rs r4rz4DeprecatedRequestAttributesTests.test_noLongerQueueds .,,w' %%$:R:R9S%T CM* .(  Y'! 5 r3N)r.r/r0r1rrr2r3r4rrs 4 r3rcbeZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZy)ChannelProductionTestsz= Tests for the way HTTPChannel manages backpressure. s#GET / HTTP/1.1 Host: localhost cx|}tj}t||_|j |||fS)a Setup a L{HTTPChannel} and a transport and associate them. @param transport: A transport to back the L{HTTPChannel} @param requestFactory: An object that can construct L{Request} objects. @return: A tuple of the channel and the transport. )r rr=rr)rFrrrs r4buildChannelAndTransportz/ChannelProductionTests.buildChannelAndTransport<s= ""$!9.!Iy) !!r3c|jtt\}}|j|j||j |j y)zu L{HTTPChannel} registers itself as a producer with its transport when a connection is made. N)rrrirQrlr streamingrFrrs r4test_HTTPChannelIsAProducerz2ChannelProductionTests.test_HTTPChannelIsAProducerKsL "::  /  ++W5  ++,r3c|jtt\}}|j|j |j d|j |j dy)zV L{HTTPChannel} unregisters itself when it has loseConnection called. N)rrrir'rkrlrrs r48test_HTTPChannelUnregistersSelfWhenCallingLoseConnectionzOChannelProductionTests.test_HTTPChannelUnregistersSelfWhenCallingLoseConnectionWsX"::  /    i(($/ i))40r3c|jtt\}}|jt d|j t |jt dy)z If two producers are registered on a L{HTTPChannel} without the first being unregistered, a L{RuntimeError} is thrown. TN)rrrirDrrYrrs r4(test_HTTPChannelRejectsMultipleProducersz?ChannelProductionTests.test_HTTPChannelRejectsMultipleProducerscsS "::  /    $7 ,(@(@-/SWXr3c|jtt\}}|j|j |j dy)zr If there is no producer, the L{HTTPChannel} can still have C{unregisterProducer} called. Nrrrirark_requestProducerrs r4+test_HTTPChannelCanUnregisterWithNoProducerzBChannelProductionTests.test_HTTPChannelCanUnregisterWithNoProduceroD "::  /  ""$ g..5r3c|jtt\}}|j|j |j dy)zn If there is no request producer currently registered, C{stopProducing} does nothing. Nrrs r4,test_HTTPChannelStopWithNoRequestOutstandingzCChannelProductionTests.test_HTTPChannelStopWithNoRequestOutstanding{rr3cx|jtt\}}|j|j|j dj }t}|j|d|j|jg|j|j|jdgy)z If there is a request producer registered with L{HTTPChannel}, calling C{stopProducing} causes that producer to be stopped as well. rTstopN) rrrrr}rrrrDrQevents stopProducingrFrrr}rls r4#test_HTTPChannelStopRequestProducerz:ChannelProductionTests.test_HTTPChannelStopRequestProducers "::  1  T\\*""1%..!?  40 "-  6(3r3c.|jtt\}}|j|jd|j |j|jd|j |j|jdy)z When L{HTTPChannel} has C{pauseProducing} called on it by the transport it will call C{pauseProducing} on the transport. When unpaused, the L{HTTPChannel} will call C{resumeProducing} on its transport. rrN)rrrirQrpauseProducingresumeProducingrs r4;test_HTTPChannelPropagatesProducingFromTransportToTransportzRChannelProductionTests.test_HTTPChannelPropagatesProducingFromTransportToTransports "::  /  00+>   00(; ! 00+>r3c$|jtt\}}d|_|j |j |j d|j dj}t}|j|d|j|jd|j|jg|j|j|jd|j|jdg|j|j|jd|j|jddg|j|j!|j|jdy) z If a L{Request} object has registered itself as a producer with a L{HTTPChannel} object, and the L{HTTPChannel} object is paused, both the transport and L{Request} objects get paused. rs123TrpauseresumerN)rrrrrr}rrrrDrQrrrrrarrs r43test_HTTPChannelPropagatesPausedProductionToRequestzJChannelProductionTests.test_HTTPChannelPropagatesPausedProductionToRequestsP "::  1 ,-( T\\*V$""1%..!?  40 00(; "-   00(; 7)4 ! 00(; 7H*=> ""$  00+>r3c|jtt\}}d|_|j |j |j d|j dj}t}|j|d|j|jd|j|jg|j|j|jd|j|jdg|j|j|j|jd|j!|j|jdy)z If a L{Request} object completes its response while the transport is paused, the L{HTTPChannel} does not resume the transport. rsextraTrrrN)rrrrrr}rrrrDrQrrrrarrrs r4/test_HTTPChannelStaysPausedWhenRequestCompleteszFChannelProductionTests.test_HTTPChannelStaysPausedWhenRequestCompletess7 "::  1 ,-( T\\*X&""1%..!?  40 00(; "-   00(; 7)4 ""$  00(; ! 00+>r3c~Gddt}|}|j|jt|j|j |t \}}|j |jd|j|j |jd|j|j|j |jd|j|jjd|j|j |jdy)z If the L{HTTPChannel} has paused the transport, it still tolerates receiving data, and does not attempt to pause the transport again. ceZdZdZdZy)gChannelProductionTests.test_HTTPChannelToleratesDataWhenTransportPaused..NoDoublePauseTransportz| A version of L{StringTransport} that fails tests if it is paused while already paused. cb|jdk(r tdtj|y)NrzTransport was paused twice!)rrrrrEs r4rzvChannelProductionTests.test_HTTPChannelToleratesDataWhenTransportPaused..NoDoublePauseTransport.pauseProducings*%%1&'DEE..t4r3N)r.r/r0r1rr2r3r4NoDoublePauseTransportrs    5r3rrrsHTTP/1.1 200 OK N)rrrYrrrirQrrr}rrrr)rFrrrs r40test_HTTPChannelToleratesDataWhenTransportPausedzGChannelProductionTests.test_HTTPChannelToleratesDataWhenTransportPaused s 5_ 5+,   " , (@(@A!:: " $&6  00+>   00(; T\\* 00(;  )445KLM ! 00+>r3c~jtt\}ttj}t |_|j|jj|jdj}|jj}fd}|j|S)z If the L{HTTPChannel} has a L{IPullProducer} registered with it it can adapt that producer into an L{IPushProducer}. rctjjddd}d}j||y)Nrr*s<1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 )rrrQ)ign responseBodyexpectedResponseBodyrFrs r4validatezOChannelProductionTests.test_HTTPChannelToleratesPullProducers..validateHs>$??,22;B1EL  !   \+? @r3)rrr?r rDummyPullProducerHandlerProxyrrrr}rrrBrYr)rFrr}responseCompleterrs` @r4&test_HTTPChannelToleratesPullProducersz=ChannelProductionTests.test_HTTPChannelToleratesPullProducers7s "::  7 $% ""$!>y)T\\*""1%.."2299 A  ++H55r3ct}t}tj}d|_|j |_|j ||jd|j|j||j|jd|jd|j|jd|j|jdy)zS L{HTTPChannel} unregisters itself when it times out a connection. rrTr*N) rrr rrrrrrkrlr)rFrrrs r4,test_HTTPChannelUnregistersSelfWhenTimingOutzCChannelProductionTests.test_HTTPChannelUnregistersSelfWhenTimingOutZs#% ""$!OOy)  b i(('2 i))40  a i(($/ i))40r3N)r.r/r0r1r}rrrrrrrrrrrr r r2r3r4rr5sUCG " - 1 Y 6 640?**?X(?T+?Z!6F1r3rceZdZdZdZy)HTTPChannelSanitizationTestsz8 Test that L{HTTPChannel} sanitizes its output. c HtD]}t}tj}|j ||j ddd||fgdj ttgdz}|j|jdj d|dgy ) z L{HTTPChannel.writeHeaders} removes linear whitespace from the list of header names and values it receives. rrvsOK)rycodereasonr: rrr3N) r'rr rr writeHeadersrSr(rQr)rF componentrrsanitizedHeaderLines r4*test_writeHeadersSanitizesLinearWhitespacezGHTTPChannelSanitizationTests.test_writeHeadersSanitizesLinearWhitespacews 9 I')I&&(G  " "9 -  ##Y/0 !  &&      ! *+ - r3N)r.r/r0r1rr2r3r4rrrs $r3rceZdZdZdZy)HTTPClientSanitizationTestsz< Test that L{http.HTTPClient} sanitizes its output. c,tD]}t}tj}|j ||j |||j |jjdjttggy)z L{HTTPClient.sendHeader} replaces linear whitespace in its header keys and values with a single space. rN) r'rr HTTPClientrrrQrrrSr()rFrrrs r4(test_sendHeaderSanitizesLinearWhitespacezDHTTPClientSanitizationTests.test_sendHeaderSanitizesLinearWhitespacesz 9 I')I__&F  ! !) ,   i 3   !,,.^^<=>   r3N)r.r/r0r1rr2r3r4rrs  r3rc,eZdZdZdZdZdZdZdZy)HexHelperTestszM Test the L{http._hexint} and L{http._ishexdigits} helper functions. )r3s0x1234sfedss-123+123c\dD]'}|jdtj|)y)zr L{_ishexdigits()} returns L{True} for nonempy bytestrings containing hexadecimal digits. )rsabcdefsAB1234sfeds 123467890TN)rkr _ishexdigitsrFrs r4 test_isHexzHexHelperTests.test_isHexs- E 6A MM$ 1 1! 4 5 6r3c|jdtjd|jdtjd|jdtjdy)zK L{_hexint()} returns the integer equivalent of the input. rrri#Ѽ sabCD123N)rQr _hexintrEs r4 test_decodeszHexHelperTests.test_decodessO T\\$/0 t||E23 DLL$<=r3cp|jD]'}|jdtj|)y)z L{_ishexdigits()} returns L{False} for bytestrings that don't contain hexadecimal digits, including the empty string. FN) badStringsrkr r r!s r4 test_isNotHexzHexHelperTests.test_isNotHexs0  7A MM%!2!21!5 6 7r3cp|jD]'}|jttj|)y)zb L{_hexint()} raises L{ValueError} for bytestrings that can't be decoded. N)r(rYrZr r%r!s r4test_decodeNotHexz HexHelperTests.test_decodeNotHexs-  ;A   j$,, : ;r3N) r.r/r0r1r(r"r&r)r+r2r3r4rrs"7;r3r)pr1rrbrMior itertoolsrtypingrrrr urllib.parser r r zope.interfacer r rzope.interface.verifyrrEtwisted.internetrtwisted.internet.errorrrtwisted.internet.taskrtwisted.internet.testingrrrtwisted.loggerrtwisted.protocolsrtwisted.python.compatrrtwisted.python.componentsrtwisted.python.failurertwisted.test.test_internetr twisted.trialtwisted.trial.unittestr twisted.webr r!r"twisted.web.httpr#r$r%twisted.web.test.requesthelperr&r'r(r)_utilr+rvr-r=r+r?r rJrirINonQueuedRequestFactoryrDummyNewHTTPHandlerProxyrrrrrrrrrrr r#r-r;rsrrrrrPrrZrqrtrrrrrrSynchronousTestCaserrrr2r3r4rEsM  "$-AA.$A' .&:7*4"+00SS / 66. ;t|| ;!99Q R H%% <t||"11AB $ ' '(1*1)144GH ') '33EF,,,!7!7HcA8$$&7cAL0<0f,. :< :p5(++->p5f%H%%%D))H%%))XZDh//ZDz3))3l/ x((/ dD8HD8NQ 8#4#4Q h uEH%%'8uEpI 8$$I XRO(++ROj4??)x00).U:8$$&7U:p k'H--k'\N 8#4#46GN b#"4 x'8'84 nz1X..z1z )8#?#?)X(">">*%;X11%;r3