test_http.py 116 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558
  1. # Copyright (c) Twisted Matrix Laboratories.
  2. # See LICENSE for details.
  3. """
  4. Test HTTP support.
  5. """
  6. from __future__ import absolute_import, division
  7. import random, cgi, base64, calendar
  8. try:
  9. from urlparse import urlparse, urlunsplit, clear_cache
  10. except ImportError:
  11. from urllib.parse import urlparse, urlunsplit, clear_cache
  12. from zope.interface import provider
  13. from zope.interface.verify import verifyObject
  14. from twisted.python.compat import (_PY3, iterbytes, networkString, unicode,
  15. intToBytes, NativeStringIO)
  16. from twisted.python.components import proxyForInterface
  17. from twisted.python.failure import Failure
  18. from twisted.trial import unittest
  19. from twisted.trial.unittest import TestCase
  20. from twisted.web import http, http_headers, iweb
  21. from twisted.web.http import PotentialDataLoss, _DataLoss
  22. from twisted.web.http import _IdentityTransferDecoder
  23. from twisted.internet.task import Clock
  24. from twisted.internet.error import ConnectionLost
  25. from twisted.protocols import loopback
  26. from twisted.test.proto_helpers import StringTransport, NonStreamingProducer
  27. from twisted.test.test_internet import DummyProducer
  28. from twisted.web.test.requesthelper import DummyChannel
  29. from zope.interface import directlyProvides, providedBy
  30. class _IDeprecatedHTTPChannelToRequestInterfaceProxy(proxyForInterface(
  31. http._IDeprecatedHTTPChannelToRequestInterface)):
  32. """
  33. Proxy L{_IDeprecatedHTTPChannelToRequestInterface}. Used to
  34. assert that the interface matches what L{HTTPChannel} expects.
  35. """
  36. def _makeRequestProxyFactory(clsToWrap):
  37. """
  38. Return a callable that proxies instances of C{clsToWrap} via
  39. L{_IDeprecatedHTTPChannelToRequestInterface}.
  40. @param clsToWrap: The class whose instances will be proxied.
  41. @type cls: L{_IDeprecatedHTTPChannelToRequestInterface}
  42. implementer.
  43. @return: A factory that returns
  44. L{_IDeprecatedHTTPChannelToRequestInterface} proxies.
  45. @rtype: L{callable} whose interface matches C{clsToWrap}'s constructor.
  46. """
  47. def _makeRequestProxy(*args, **kwargs):
  48. instance = clsToWrap(*args, **kwargs)
  49. return _IDeprecatedHTTPChannelToRequestInterfaceProxy(instance)
  50. # For INonQueuedRequestFactory
  51. directlyProvides(_makeRequestProxy, providedBy(clsToWrap))
  52. return _makeRequestProxy
  53. class DummyPullProducerHandler(http.Request):
  54. """
  55. An HTTP request handler that registers a dummy pull producer to serve the
  56. body.
  57. The owner must call C{finish} to complete the response.
  58. """
  59. def process(self):
  60. self._actualProducer = NonStreamingProducer(self)
  61. self.setResponseCode(200)
  62. self.registerProducer(self._actualProducer, False)
  63. DummyPullProducerHandlerProxy = _makeRequestProxyFactory(
  64. DummyPullProducerHandler)
  65. class DateTimeTests(unittest.TestCase):
  66. """Test date parsing functions."""
  67. def testRoundtrip(self):
  68. for i in range(10000):
  69. time = random.randint(0, 2000000000)
  70. timestr = http.datetimeToString(time)
  71. time2 = http.stringToDatetime(timestr)
  72. self.assertEqual(time, time2)
  73. def testStringToDatetime(self):
  74. dateStrings = [
  75. b"Sun, 06 Nov 1994 08:49:37 GMT",
  76. b"06 Nov 1994 08:49:37 GMT",
  77. b"Sunday, 06-Nov-94 08:49:37 GMT",
  78. b"06-Nov-94 08:49:37 GMT",
  79. b"Sunday, 06-Nov-1994 08:49:37 GMT",
  80. b"06-Nov-1994 08:49:37 GMT",
  81. b"Sun Nov 6 08:49:37 1994",
  82. b"Nov 6 08:49:37 1994",
  83. ]
  84. dateInt = calendar.timegm((1994, 11, 6, 8, 49, 37, 6, 6, 0))
  85. for dateString in dateStrings:
  86. self.assertEqual(http.stringToDatetime(dateString), dateInt)
  87. self.assertEqual(
  88. http.stringToDatetime(b"Thursday, 29-Sep-16 17:15:29 GMT"),
  89. calendar.timegm((2016, 9, 29, 17, 15, 29, 3, 273, 0)))
  90. class DummyHTTPHandler(http.Request):
  91. def process(self):
  92. self.content.seek(0, 0)
  93. data = self.content.read()
  94. length = self.getHeader(b'content-length')
  95. if length is None:
  96. length = networkString(str(length))
  97. request = b"'''\n" + length + b"\n" + data + b"'''\n"
  98. self.setResponseCode(200)
  99. self.setHeader(b"Request", self.uri)
  100. self.setHeader(b"Command", self.method)
  101. self.setHeader(b"Version", self.clientproto)
  102. self.setHeader(b"Content-Length", intToBytes(len(request)))
  103. self.write(request)
  104. self.finish()
  105. DummyHTTPHandlerProxy = _makeRequestProxyFactory(DummyHTTPHandler)
  106. @provider(iweb.INonQueuedRequestFactory)
  107. class DummyNewHTTPHandler(DummyHTTPHandler):
  108. """
  109. This is exactly like the DummyHTTPHandler but it takes only one argument
  110. in its constructor, with no default arguments. This exists to test an
  111. alternative code path in L{HTTPChannel}.
  112. """
  113. def __init__(self, channel):
  114. DummyHTTPHandler.__init__(self, channel)
  115. DummyNewHTTPHandlerProxy = _makeRequestProxyFactory(DummyNewHTTPHandler)
  116. class DelayedHTTPHandler(DummyHTTPHandler):
  117. """
  118. Like L{DummyHTTPHandler}, but doesn't respond immediately.
  119. """
  120. def process(self):
  121. pass
  122. def delayedProcess(self):
  123. DummyHTTPHandler.process(self)
  124. DelayedHTTPHandlerProxy = _makeRequestProxyFactory(DelayedHTTPHandler)
  125. class LoopbackHTTPClient(http.HTTPClient):
  126. def connectionMade(self):
  127. self.sendCommand(b"GET", b"/foo/bar")
  128. self.sendHeader(b"Content-Length", 10)
  129. self.endHeaders()
  130. self.transport.write(b"0123456789")
  131. def parametrizeTimeoutMixin(protocol, reactor):
  132. """
  133. Parametrizes the L{TimeoutMixin} so that it works with whatever reactor is
  134. being used by the test.
  135. @param protocol: A L{_GenericHTTPChannel} or something implementing a
  136. similar interface.
  137. @type protocol: L{_GenericHTTPChannel}
  138. @param reactor: An L{IReactorTime} implementation.
  139. @type reactor: L{IReactorTime}
  140. @return: The C{channel}, with its C{callLater} method patched.
  141. """
  142. # This is a terrible violation of the abstraction later of
  143. # _genericHTTPChannelProtocol, but we need to do it because
  144. # policies.TimeoutMixin doesn't accept a reactor on the object.
  145. # See https://twistedmatrix.com/trac/ticket/8488
  146. protocol._channel.callLater = reactor.callLater
  147. return protocol
  148. class ResponseTestMixin(object):
  149. """
  150. A mixin that provides a simple means of comparing an actual response string
  151. to an expected response string by performing the minimal parsing.
  152. """
  153. def assertResponseEquals(self, responses, expected):
  154. """
  155. Assert that the C{responses} matches the C{expected} responses.
  156. @type responses: C{bytes}
  157. @param responses: The bytes sent in response to one or more requests.
  158. @type expected: C{list} of C{tuple} of C{bytes}
  159. @param expected: The expected values for the responses. Each tuple
  160. element of the list represents one response. Each byte string
  161. element of the tuple is a full header line without delimiter, except
  162. for the last element which gives the full response body.
  163. """
  164. for response in expected:
  165. expectedHeaders, expectedContent = response[:-1], response[-1]
  166. # Intentionally avoid mutating the inputs here.
  167. expectedStatus = expectedHeaders[0]
  168. expectedHeaders = expectedHeaders[1:]
  169. headers, rest = responses.split(b'\r\n\r\n', 1)
  170. headers = headers.splitlines()
  171. status = headers.pop(0)
  172. self.assertEqual(expectedStatus, status)
  173. self.assertEqual(set(headers), set(expectedHeaders))
  174. content = rest[:len(expectedContent)]
  175. responses = rest[len(expectedContent):]
  176. self.assertEqual(content, expectedContent)
  177. class HTTP1_0Tests(unittest.TestCase, ResponseTestMixin):
  178. requests = (
  179. b"GET / HTTP/1.0\r\n"
  180. b"\r\n"
  181. b"GET / HTTP/1.1\r\n"
  182. b"Accept: text/html\r\n"
  183. b"\r\n")
  184. expected_response = [
  185. (b"HTTP/1.0 200 OK",
  186. b"Request: /",
  187. b"Command: GET",
  188. b"Version: HTTP/1.0",
  189. b"Content-Length: 13",
  190. b"'''\nNone\n'''\n")]
  191. def test_buffer(self):
  192. """
  193. Send requests over a channel and check responses match what is expected.
  194. """
  195. b = StringTransport()
  196. a = http.HTTPChannel()
  197. a.requestFactory = DummyHTTPHandlerProxy
  198. a.makeConnection(b)
  199. # one byte at a time, to stress it.
  200. for byte in iterbytes(self.requests):
  201. a.dataReceived(byte)
  202. a.connectionLost(IOError("all one"))
  203. value = b.value()
  204. self.assertResponseEquals(value, self.expected_response)
  205. def test_requestBodyTimeout(self):
  206. """
  207. L{HTTPChannel} resets its timeout whenever data from a request body is
  208. delivered to it.
  209. """
  210. clock = Clock()
  211. transport = StringTransport()
  212. protocol = http.HTTPChannel()
  213. protocol.timeOut = 100
  214. protocol.callLater = clock.callLater
  215. protocol.makeConnection(transport)
  216. protocol.dataReceived(b'POST / HTTP/1.0\r\nContent-Length: 2\r\n\r\n')
  217. clock.advance(99)
  218. self.assertFalse(transport.disconnecting)
  219. protocol.dataReceived(b'x')
  220. clock.advance(99)
  221. self.assertFalse(transport.disconnecting)
  222. protocol.dataReceived(b'x')
  223. self.assertEqual(len(protocol.requests), 1)
  224. def test_requestBodyDefaultTimeout(self):
  225. """
  226. L{HTTPChannel}'s default timeout is 60 seconds.
  227. """
  228. clock = Clock()
  229. transport = StringTransport()
  230. factory = http.HTTPFactory()
  231. protocol = factory.buildProtocol(None)
  232. protocol = parametrizeTimeoutMixin(protocol, clock)
  233. protocol.makeConnection(transport)
  234. protocol.dataReceived(b'POST / HTTP/1.0\r\nContent-Length: 2\r\n\r\n')
  235. clock.advance(59)
  236. self.assertFalse(transport.disconnecting)
  237. clock.advance(1)
  238. self.assertTrue(transport.disconnecting)
  239. def test_transportForciblyClosed(self):
  240. """
  241. If a timed out transport doesn't close after 15 seconds, the
  242. L{HTTPChannel} will forcibly close it.
  243. """
  244. clock = Clock()
  245. transport = StringTransport()
  246. factory = http.HTTPFactory()
  247. protocol = factory.buildProtocol(None)
  248. protocol = parametrizeTimeoutMixin(protocol, clock)
  249. protocol.makeConnection(transport)
  250. protocol.dataReceived(b'POST / HTTP/1.0\r\nContent-Length: 2\r\n\r\n')
  251. self.assertFalse(transport.disconnecting)
  252. self.assertFalse(transport.disconnected)
  253. # Force the initial timeout.
  254. clock.advance(60)
  255. self.assertTrue(transport.disconnecting)
  256. self.assertFalse(transport.disconnected)
  257. # Watch the transport get force-closed.
  258. clock.advance(14)
  259. self.assertTrue(transport.disconnecting)
  260. self.assertFalse(transport.disconnected)
  261. clock.advance(1)
  262. self.assertTrue(transport.disconnecting)
  263. self.assertTrue(transport.disconnected)
  264. def test_transportNotAbortedAfterConnectionLost(self):
  265. """
  266. If a timed out transport ends up calling C{connectionLost}, it prevents
  267. the force-closure of the transport.
  268. """
  269. clock = Clock()
  270. transport = StringTransport()
  271. factory = http.HTTPFactory()
  272. protocol = factory.buildProtocol(None)
  273. protocol = parametrizeTimeoutMixin(protocol, clock)
  274. protocol.makeConnection(transport)
  275. protocol.dataReceived(b'POST / HTTP/1.0\r\nContent-Length: 2\r\n\r\n')
  276. self.assertFalse(transport.disconnecting)
  277. self.assertFalse(transport.disconnected)
  278. # Force the initial timeout.
  279. clock.advance(60)
  280. self.assertTrue(transport.disconnecting)
  281. self.assertFalse(transport.disconnected)
  282. # Move forward nearly to the timeout, then fire connectionLost.
  283. clock.advance(14)
  284. protocol.connectionLost(None)
  285. # Check that the transport isn't forcibly closed.
  286. clock.advance(1)
  287. self.assertTrue(transport.disconnecting)
  288. self.assertFalse(transport.disconnected)
  289. def test_transportNotAbortedWithZeroAbortTimeout(self):
  290. """
  291. If the L{HTTPChannel} has its c{abortTimeout} set to L{None}, it never
  292. aborts.
  293. """
  294. clock = Clock()
  295. transport = StringTransport()
  296. factory = http.HTTPFactory()
  297. protocol = factory.buildProtocol(None)
  298. protocol._channel.abortTimeout = None
  299. protocol = parametrizeTimeoutMixin(protocol, clock)
  300. protocol.makeConnection(transport)
  301. protocol.dataReceived(b'POST / HTTP/1.0\r\nContent-Length: 2\r\n\r\n')
  302. self.assertFalse(transport.disconnecting)
  303. self.assertFalse(transport.disconnected)
  304. # Force the initial timeout.
  305. clock.advance(60)
  306. self.assertTrue(transport.disconnecting)
  307. self.assertFalse(transport.disconnected)
  308. # Move an absurdly long way just to prove the point.
  309. clock.advance(2**32)
  310. self.assertTrue(transport.disconnecting)
  311. self.assertFalse(transport.disconnected)
  312. def test_noPipeliningApi(self):
  313. """
  314. Test that a L{http.Request} subclass with no queued kwarg works as
  315. expected.
  316. """
  317. b = StringTransport()
  318. a = http.HTTPChannel()
  319. a.requestFactory = DummyHTTPHandlerProxy
  320. a.makeConnection(b)
  321. # one byte at a time, to stress it.
  322. for byte in iterbytes(self.requests):
  323. a.dataReceived(byte)
  324. a.connectionLost(IOError("all done"))
  325. value = b.value()
  326. self.assertResponseEquals(value, self.expected_response)
  327. def test_noPipelining(self):
  328. """
  329. Test that pipelined requests get buffered, not processed in parallel.
  330. """
  331. b = StringTransport()
  332. a = http.HTTPChannel()
  333. a.requestFactory = DelayedHTTPHandlerProxy
  334. a.makeConnection(b)
  335. # one byte at a time, to stress it.
  336. for byte in iterbytes(self.requests):
  337. a.dataReceived(byte)
  338. value = b.value()
  339. # So far only one request should have been dispatched.
  340. self.assertEqual(value, b'')
  341. self.assertEqual(1, len(a.requests))
  342. # Now, process each request one at a time.
  343. while a.requests:
  344. self.assertEqual(1, len(a.requests))
  345. request = a.requests[0].original
  346. request.delayedProcess()
  347. value = b.value()
  348. self.assertResponseEquals(value, self.expected_response)
  349. class HTTP1_1Tests(HTTP1_0Tests):
  350. requests = (
  351. b"GET / HTTP/1.1\r\n"
  352. b"Accept: text/html\r\n"
  353. b"\r\n"
  354. b"POST / HTTP/1.1\r\n"
  355. b"Content-Length: 10\r\n"
  356. b"\r\n"
  357. b"0123456789POST / HTTP/1.1\r\n"
  358. b"Content-Length: 10\r\n"
  359. b"\r\n"
  360. b"0123456789HEAD / HTTP/1.1\r\n"
  361. b"\r\n")
  362. expected_response = [
  363. (b"HTTP/1.1 200 OK",
  364. b"Request: /",
  365. b"Command: GET",
  366. b"Version: HTTP/1.1",
  367. b"Content-Length: 13",
  368. b"'''\nNone\n'''\n"),
  369. (b"HTTP/1.1 200 OK",
  370. b"Request: /",
  371. b"Command: POST",
  372. b"Version: HTTP/1.1",
  373. b"Content-Length: 21",
  374. b"'''\n10\n0123456789'''\n"),
  375. (b"HTTP/1.1 200 OK",
  376. b"Request: /",
  377. b"Command: POST",
  378. b"Version: HTTP/1.1",
  379. b"Content-Length: 21",
  380. b"'''\n10\n0123456789'''\n"),
  381. (b"HTTP/1.1 200 OK",
  382. b"Request: /",
  383. b"Command: HEAD",
  384. b"Version: HTTP/1.1",
  385. b"Content-Length: 13",
  386. b"")]
  387. class HTTP1_1_close_Tests(HTTP1_0Tests):
  388. requests = (
  389. b"GET / HTTP/1.1\r\n"
  390. b"Accept: text/html\r\n"
  391. b"Connection: close\r\n"
  392. b"\r\n"
  393. b"GET / HTTP/1.0\r\n"
  394. b"\r\n")
  395. expected_response = [
  396. (b"HTTP/1.1 200 OK",
  397. b"Connection: close",
  398. b"Request: /",
  399. b"Command: GET",
  400. b"Version: HTTP/1.1",
  401. b"Content-Length: 13",
  402. b"'''\nNone\n'''\n")]
  403. class HTTP0_9Tests(HTTP1_0Tests):
  404. requests = (
  405. b"GET /\r\n")
  406. expected_response = b"HTTP/1.1 400 Bad Request\r\n\r\n"
  407. def assertResponseEquals(self, response, expectedResponse):
  408. self.assertEqual(response, expectedResponse)
  409. def test_noPipelining(self):
  410. raise unittest.SkipTest("HTTP/0.9 not supported")
  411. class PipeliningBodyTests(unittest.TestCase, ResponseTestMixin):
  412. """
  413. Tests that multiple pipelined requests with bodies are correctly buffered.
  414. """
  415. requests = (
  416. b"POST / HTTP/1.1\r\n"
  417. b"Content-Length: 10\r\n"
  418. b"\r\n"
  419. b"0123456789POST / HTTP/1.1\r\n"
  420. b"Content-Length: 10\r\n"
  421. b"\r\n"
  422. b"0123456789"
  423. )
  424. expectedResponses = [
  425. (b"HTTP/1.1 200 OK",
  426. b"Request: /",
  427. b"Command: POST",
  428. b"Version: HTTP/1.1",
  429. b"Content-Length: 21",
  430. b"'''\n10\n0123456789'''\n"),
  431. (b"HTTP/1.1 200 OK",
  432. b"Request: /",
  433. b"Command: POST",
  434. b"Version: HTTP/1.1",
  435. b"Content-Length: 21",
  436. b"'''\n10\n0123456789'''\n")]
  437. def test_noPipelining(self):
  438. """
  439. Test that pipelined requests get buffered, not processed in parallel.
  440. """
  441. b = StringTransport()
  442. a = http.HTTPChannel()
  443. a.requestFactory = DelayedHTTPHandlerProxy
  444. a.makeConnection(b)
  445. # one byte at a time, to stress it.
  446. for byte in iterbytes(self.requests):
  447. a.dataReceived(byte)
  448. value = b.value()
  449. # So far only one request should have been dispatched.
  450. self.assertEqual(value, b'')
  451. self.assertEqual(1, len(a.requests))
  452. # Now, process each request one at a time.
  453. while a.requests:
  454. self.assertEqual(1, len(a.requests))
  455. request = a.requests[0].original
  456. request.delayedProcess()
  457. value = b.value()
  458. self.assertResponseEquals(value, self.expectedResponses)
  459. class ShutdownTests(unittest.TestCase):
  460. """
  461. Tests that connections can be shut down by L{http.Request} objects.
  462. """
  463. class ShutdownHTTPHandler(http.Request):
  464. """
  465. A HTTP handler that just immediately calls loseConnection.
  466. """
  467. def process(self):
  468. self.loseConnection()
  469. request = (
  470. b"POST / HTTP/1.1\r\n"
  471. b"Content-Length: 10\r\n"
  472. b"\r\n"
  473. b"0123456789"
  474. )
  475. def test_losingConnection(self):
  476. """
  477. Calling L{http.Request.loseConnection} causes the transport to be
  478. disconnected.
  479. """
  480. b = StringTransport()
  481. a = http.HTTPChannel()
  482. a.requestFactory = _makeRequestProxyFactory(self.ShutdownHTTPHandler)
  483. a.makeConnection(b)
  484. a.dataReceived(self.request)
  485. # The transport should have been shut down.
  486. self.assertTrue(b.disconnecting)
  487. # No response should have been written.
  488. value = b.value()
  489. self.assertEqual(value, b'')
  490. class SecurityTests(unittest.TestCase):
  491. """
  492. Tests that L{http.Request.isSecure} correctly takes the transport into
  493. account.
  494. """
  495. def test_isSecure(self):
  496. """
  497. Calling L{http.Request.isSecure} when the channel is backed with a
  498. secure transport will return L{True}.
  499. """
  500. b = DummyChannel.SSL()
  501. a = http.HTTPChannel()
  502. a.makeConnection(b)
  503. req = http.Request(a)
  504. self.assertTrue(req.isSecure())
  505. def test_notSecure(self):
  506. """
  507. Calling L{http.Request.isSecure} when the channel is not backed with a
  508. secure transport will return L{False}.
  509. """
  510. b = DummyChannel.TCP()
  511. a = http.HTTPChannel()
  512. a.makeConnection(b)
  513. req = http.Request(a)
  514. self.assertFalse(req.isSecure())
  515. def test_notSecureAfterFinish(self):
  516. """
  517. After a request is finished, calling L{http.Request.isSecure} will
  518. always return L{False}.
  519. """
  520. b = DummyChannel.SSL()
  521. a = http.HTTPChannel()
  522. a.makeConnection(b)
  523. req = http.Request(a)
  524. a.requests.append(req)
  525. req.setResponseCode(200)
  526. req.finish()
  527. self.assertFalse(req.isSecure())
  528. class GenericHTTPChannelTests(unittest.TestCase):
  529. """
  530. Tests for L{http._genericHTTPChannelProtocol}, a L{HTTPChannel}-alike which
  531. can handle different HTTP protocol channels.
  532. """
  533. requests = (
  534. b"GET / HTTP/1.1\r\n"
  535. b"Accept: text/html\r\n"
  536. b"Connection: close\r\n"
  537. b"\r\n"
  538. b"GET / HTTP/1.0\r\n"
  539. b"\r\n")
  540. def _negotiatedProtocolForTransportInstance(self, t):
  541. """
  542. Run a request using the specific instance of a transport. Returns the
  543. negotiated protocol string.
  544. """
  545. a = http._genericHTTPChannelProtocolFactory(b'')
  546. a.requestFactory = DummyHTTPHandlerProxy
  547. a.makeConnection(t)
  548. # one byte at a time, to stress it.
  549. for byte in iterbytes(self.requests):
  550. a.dataReceived(byte)
  551. a.connectionLost(IOError("all done"))
  552. return a._negotiatedProtocol
  553. def test_protocolUnspecified(self):
  554. """
  555. If the transport has no support for protocol negotiation (no
  556. negotiatedProtocol attribute), HTTP/1.1 is assumed.
  557. """
  558. b = StringTransport()
  559. negotiatedProtocol = self._negotiatedProtocolForTransportInstance(b)
  560. self.assertEqual(negotiatedProtocol, b'http/1.1')
  561. def test_protocolNone(self):
  562. """
  563. If the transport has no support for protocol negotiation (returns None
  564. for negotiatedProtocol), HTTP/1.1 is assumed.
  565. """
  566. b = StringTransport()
  567. b.negotiatedProtocol = None
  568. negotiatedProtocol = self._negotiatedProtocolForTransportInstance(b)
  569. self.assertEqual(negotiatedProtocol, b'http/1.1')
  570. def test_http11(self):
  571. """
  572. If the transport reports that HTTP/1.1 is negotiated, that's what's
  573. negotiated.
  574. """
  575. b = StringTransport()
  576. b.negotiatedProtocol = b'http/1.1'
  577. negotiatedProtocol = self._negotiatedProtocolForTransportInstance(b)
  578. self.assertEqual(negotiatedProtocol, b'http/1.1')
  579. def test_http2_present(self):
  580. """
  581. If the transport reports that HTTP/2 is negotiated and HTTP/2 is
  582. present, that's what's negotiated.
  583. """
  584. b = StringTransport()
  585. b.negotiatedProtocol = b'h2'
  586. negotiatedProtocol = self._negotiatedProtocolForTransportInstance(b)
  587. self.assertEqual(negotiatedProtocol, b'h2')
  588. if not http.H2_ENABLED:
  589. test_http2_present.skip = "HTTP/2 support not present"
  590. def test_http2_absent(self):
  591. """
  592. If the transport reports that HTTP/2 is negotiated and HTTP/2 is not
  593. present, an error is encountered.
  594. """
  595. b = StringTransport()
  596. b.negotiatedProtocol = b'h2'
  597. self.assertRaises(
  598. ValueError,
  599. self._negotiatedProtocolForTransportInstance,
  600. b,
  601. )
  602. if http.H2_ENABLED:
  603. test_http2_absent.skip = "HTTP/2 support present"
  604. def test_unknownProtocol(self):
  605. """
  606. If the transport reports that a protocol other than HTTP/1.1 or HTTP/2
  607. is negotiated, an error occurs.
  608. """
  609. b = StringTransport()
  610. b.negotiatedProtocol = b'smtp'
  611. self.assertRaises(
  612. AssertionError,
  613. self._negotiatedProtocolForTransportInstance,
  614. b,
  615. )
  616. def test_factory(self):
  617. """
  618. The C{factory} attribute is taken from the inner channel.
  619. """
  620. a = http._genericHTTPChannelProtocolFactory(b'')
  621. a._channel.factory = b"Foo"
  622. self.assertEqual(a.factory, b"Foo")
  623. def test_GenericHTTPChannelPropagatesCallLater(self):
  624. """
  625. If C{callLater} is patched onto the L{http._GenericHTTPChannelProtocol}
  626. then we need to propagate it through to the backing channel.
  627. """
  628. clock = Clock()
  629. factory = http.HTTPFactory(reactor=clock)
  630. protocol = factory.buildProtocol(None)
  631. self.assertEqual(protocol.callLater, clock.callLater)
  632. self.assertEqual(protocol._channel.callLater, clock.callLater)
  633. def test_genericHTTPChannelCallLaterUpgrade(self):
  634. """
  635. If C{callLater} is patched onto the L{http._GenericHTTPChannelProtocol}
  636. then we need to propagate it across onto a new backing channel after
  637. upgrade.
  638. """
  639. clock = Clock()
  640. factory = http.HTTPFactory(reactor=clock)
  641. protocol = factory.buildProtocol(None)
  642. self.assertEqual(protocol.callLater, clock.callLater)
  643. self.assertEqual(protocol._channel.callLater, clock.callLater)
  644. transport = StringTransport()
  645. transport.negotiatedProtocol = b'h2'
  646. protocol.requestFactory = DummyHTTPHandler
  647. protocol.makeConnection(transport)
  648. # Send a byte to make it think the handshake is done.
  649. protocol.dataReceived(b'P')
  650. self.assertEqual(protocol.callLater, clock.callLater)
  651. self.assertEqual(protocol._channel.callLater, clock.callLater)
  652. if not http.H2_ENABLED:
  653. test_genericHTTPChannelCallLaterUpgrade.skip = (
  654. "HTTP/2 support not present"
  655. )
  656. def test_unregistersProducer(self):
  657. """
  658. The L{_GenericHTTPChannelProtocol} will unregister its proxy channel
  659. from the transport if upgrade is negotiated.
  660. """
  661. transport = StringTransport()
  662. transport.negotiatedProtocol = b'h2'
  663. genericProtocol = http._genericHTTPChannelProtocolFactory(b'')
  664. genericProtocol.requestFactory = DummyHTTPHandlerProxy
  665. genericProtocol.makeConnection(transport)
  666. # We expect the transport has a underlying channel registered as
  667. # a producer.
  668. self.assertIs(transport.producer, genericProtocol._channel)
  669. # Force the upgrade.
  670. genericProtocol.dataReceived(b'P')
  671. # The transport should now have no producer.
  672. self.assertIs(transport.producer, None)
  673. if not http.H2_ENABLED:
  674. test_unregistersProducer.skip = "HTTP/2 support not present"
  675. class HTTPLoopbackTests(unittest.TestCase):
  676. expectedHeaders = {b'request': b'/foo/bar',
  677. b'command': b'GET',
  678. b'version': b'HTTP/1.0',
  679. b'content-length': b'21'}
  680. numHeaders = 0
  681. gotStatus = 0
  682. gotResponse = 0
  683. gotEndHeaders = 0
  684. def _handleStatus(self, version, status, message):
  685. self.gotStatus = 1
  686. self.assertEqual(version, b"HTTP/1.0")
  687. self.assertEqual(status, b"200")
  688. def _handleResponse(self, data):
  689. self.gotResponse = 1
  690. self.assertEqual(data, b"'''\n10\n0123456789'''\n")
  691. def _handleHeader(self, key, value):
  692. self.numHeaders = self.numHeaders + 1
  693. self.assertEqual(self.expectedHeaders[key.lower()], value)
  694. def _handleEndHeaders(self):
  695. self.gotEndHeaders = 1
  696. self.assertEqual(self.numHeaders, 4)
  697. def testLoopback(self):
  698. server = http.HTTPChannel()
  699. server.requestFactory = DummyHTTPHandlerProxy
  700. client = LoopbackHTTPClient()
  701. client.handleResponse = self._handleResponse
  702. client.handleHeader = self._handleHeader
  703. client.handleEndHeaders = self._handleEndHeaders
  704. client.handleStatus = self._handleStatus
  705. d = loopback.loopbackAsync(server, client)
  706. d.addCallback(self._cbTestLoopback)
  707. return d
  708. def _cbTestLoopback(self, ignored):
  709. if not (self.gotStatus and self.gotResponse and self.gotEndHeaders):
  710. raise RuntimeError(
  711. "didn't got all callbacks %s"
  712. % [self.gotStatus, self.gotResponse, self.gotEndHeaders])
  713. del self.gotEndHeaders
  714. del self.gotResponse
  715. del self.gotStatus
  716. del self.numHeaders
  717. def _prequest(**headers):
  718. """
  719. Make a request with the given request headers for the persistence tests.
  720. """
  721. request = http.Request(DummyChannel(), False)
  722. for headerName, v in headers.items():
  723. request.requestHeaders.setRawHeaders(networkString(headerName), v)
  724. return request
  725. class PersistenceTests(unittest.TestCase):
  726. """
  727. Tests for persistent HTTP connections.
  728. """
  729. def setUp(self):
  730. self.channel = http.HTTPChannel()
  731. self.request = _prequest()
  732. def test_http09(self):
  733. """
  734. After being used for an I{HTTP/0.9} request, the L{HTTPChannel} is not
  735. persistent.
  736. """
  737. persist = self.channel.checkPersistence(self.request, b"HTTP/0.9")
  738. self.assertFalse(persist)
  739. self.assertEqual(
  740. [], list(self.request.responseHeaders.getAllRawHeaders()))
  741. def test_http10(self):
  742. """
  743. After being used for an I{HTTP/1.0} request, the L{HTTPChannel} is not
  744. persistent.
  745. """
  746. persist = self.channel.checkPersistence(self.request, b"HTTP/1.0")
  747. self.assertFalse(persist)
  748. self.assertEqual(
  749. [], list(self.request.responseHeaders.getAllRawHeaders()))
  750. def test_http11(self):
  751. """
  752. After being used for an I{HTTP/1.1} request, the L{HTTPChannel} is
  753. persistent.
  754. """
  755. persist = self.channel.checkPersistence(self.request, b"HTTP/1.1")
  756. self.assertTrue(persist)
  757. self.assertEqual(
  758. [], list(self.request.responseHeaders.getAllRawHeaders()))
  759. def test_http11Close(self):
  760. """
  761. After being used for an I{HTTP/1.1} request with a I{Connection: Close}
  762. header, the L{HTTPChannel} is not persistent.
  763. """
  764. request = _prequest(connection=[b"close"])
  765. persist = self.channel.checkPersistence(request, b"HTTP/1.1")
  766. self.assertFalse(persist)
  767. self.assertEqual(
  768. [(b"Connection", [b"close"])],
  769. list(request.responseHeaders.getAllRawHeaders()))
  770. class IdentityTransferEncodingTests(TestCase):
  771. """
  772. Tests for L{_IdentityTransferDecoder}.
  773. """
  774. def setUp(self):
  775. """
  776. Create an L{_IdentityTransferDecoder} with callbacks hooked up so that
  777. calls to them can be inspected.
  778. """
  779. self.data = []
  780. self.finish = []
  781. self.contentLength = 10
  782. self.decoder = _IdentityTransferDecoder(
  783. self.contentLength, self.data.append, self.finish.append)
  784. def test_exactAmountReceived(self):
  785. """
  786. If L{_IdentityTransferDecoder.dataReceived} is called with a byte string
  787. with length equal to the content length passed to
  788. L{_IdentityTransferDecoder}'s initializer, the data callback is invoked
  789. with that string and the finish callback is invoked with a zero-length
  790. string.
  791. """
  792. self.decoder.dataReceived(b'x' * self.contentLength)
  793. self.assertEqual(self.data, [b'x' * self.contentLength])
  794. self.assertEqual(self.finish, [b''])
  795. def test_shortStrings(self):
  796. """
  797. If L{_IdentityTransferDecoder.dataReceived} is called multiple times
  798. with byte strings which, when concatenated, are as long as the content
  799. length provided, the data callback is invoked with each string and the
  800. finish callback is invoked only after the second call.
  801. """
  802. self.decoder.dataReceived(b'x')
  803. self.assertEqual(self.data, [b'x'])
  804. self.assertEqual(self.finish, [])
  805. self.decoder.dataReceived(b'y' * (self.contentLength - 1))
  806. self.assertEqual(self.data, [b'x', b'y' * (self.contentLength - 1)])
  807. self.assertEqual(self.finish, [b''])
  808. def test_longString(self):
  809. """
  810. If L{_IdentityTransferDecoder.dataReceived} is called with a byte string
  811. with length greater than the provided content length, only the prefix
  812. of that string up to the content length is passed to the data callback
  813. and the remainder is passed to the finish callback.
  814. """
  815. self.decoder.dataReceived(b'x' * self.contentLength + b'y')
  816. self.assertEqual(self.data, [b'x' * self.contentLength])
  817. self.assertEqual(self.finish, [b'y'])
  818. def test_rejectDataAfterFinished(self):
  819. """
  820. If data is passed to L{_IdentityTransferDecoder.dataReceived} after the
  821. finish callback has been invoked, C{RuntimeError} is raised.
  822. """
  823. failures = []
  824. def finish(bytes):
  825. try:
  826. decoder.dataReceived(b'foo')
  827. except:
  828. failures.append(Failure())
  829. decoder = _IdentityTransferDecoder(5, self.data.append, finish)
  830. decoder.dataReceived(b'x' * 4)
  831. self.assertEqual(failures, [])
  832. decoder.dataReceived(b'y')
  833. failures[0].trap(RuntimeError)
  834. self.assertEqual(
  835. str(failures[0].value),
  836. "_IdentityTransferDecoder cannot decode data after finishing")
  837. def test_unknownContentLength(self):
  838. """
  839. If L{_IdentityTransferDecoder} is constructed with L{None} for the
  840. content length, it passes all data delivered to it through to the data
  841. callback.
  842. """
  843. data = []
  844. finish = []
  845. decoder = _IdentityTransferDecoder(None, data.append, finish.append)
  846. decoder.dataReceived(b'x')
  847. self.assertEqual(data, [b'x'])
  848. decoder.dataReceived(b'y')
  849. self.assertEqual(data, [b'x', b'y'])
  850. self.assertEqual(finish, [])
  851. def _verifyCallbacksUnreferenced(self, decoder):
  852. """
  853. Check the decoder's data and finish callbacks and make sure they are
  854. None in order to help avoid references cycles.
  855. """
  856. self.assertIdentical(decoder.dataCallback, None)
  857. self.assertIdentical(decoder.finishCallback, None)
  858. def test_earlyConnectionLose(self):
  859. """
  860. L{_IdentityTransferDecoder.noMoreData} raises L{_DataLoss} if it is
  861. called and the content length is known but not enough bytes have been
  862. delivered.
  863. """
  864. self.decoder.dataReceived(b'x' * (self.contentLength - 1))
  865. self.assertRaises(_DataLoss, self.decoder.noMoreData)
  866. self._verifyCallbacksUnreferenced(self.decoder)
  867. def test_unknownContentLengthConnectionLose(self):
  868. """
  869. L{_IdentityTransferDecoder.noMoreData} calls the finish callback and
  870. raises L{PotentialDataLoss} if it is called and the content length is
  871. unknown.
  872. """
  873. body = []
  874. finished = []
  875. decoder = _IdentityTransferDecoder(None, body.append, finished.append)
  876. self.assertRaises(PotentialDataLoss, decoder.noMoreData)
  877. self.assertEqual(body, [])
  878. self.assertEqual(finished, [b''])
  879. self._verifyCallbacksUnreferenced(decoder)
  880. def test_finishedConnectionLose(self):
  881. """
  882. L{_IdentityTransferDecoder.noMoreData} does not raise any exception if
  883. it is called when the content length is known and that many bytes have
  884. been delivered.
  885. """
  886. self.decoder.dataReceived(b'x' * self.contentLength)
  887. self.decoder.noMoreData()
  888. self._verifyCallbacksUnreferenced(self.decoder)
  889. class ChunkedTransferEncodingTests(unittest.TestCase):
  890. """
  891. Tests for L{_ChunkedTransferDecoder}, which turns a byte stream encoded
  892. using HTTP I{chunked} C{Transfer-Encoding} back into the original byte
  893. stream.
  894. """
  895. def test_decoding(self):
  896. """
  897. L{_ChunkedTransferDecoder.dataReceived} decodes chunked-encoded data
  898. and passes the result to the specified callback.
  899. """
  900. L = []
  901. p = http._ChunkedTransferDecoder(L.append, None)
  902. p.dataReceived(b'3\r\nabc\r\n5\r\n12345\r\n')
  903. p.dataReceived(b'a\r\n0123456789\r\n')
  904. self.assertEqual(L, [b'abc', b'12345', b'0123456789'])
  905. def test_short(self):
  906. """
  907. L{_ChunkedTransferDecoder.dataReceived} decodes chunks broken up and
  908. delivered in multiple calls.
  909. """
  910. L = []
  911. finished = []
  912. p = http._ChunkedTransferDecoder(L.append, finished.append)
  913. for s in iterbytes(b'3\r\nabc\r\n5\r\n12345\r\n0\r\n\r\n'):
  914. p.dataReceived(s)
  915. self.assertEqual(L, [b'a', b'b', b'c', b'1', b'2', b'3', b'4', b'5'])
  916. self.assertEqual(finished, [b''])
  917. def test_newlines(self):
  918. """
  919. L{_ChunkedTransferDecoder.dataReceived} doesn't treat CR LF pairs
  920. embedded in chunk bodies specially.
  921. """
  922. L = []
  923. p = http._ChunkedTransferDecoder(L.append, None)
  924. p.dataReceived(b'2\r\n\r\n\r\n')
  925. self.assertEqual(L, [b'\r\n'])
  926. def test_extensions(self):
  927. """
  928. L{_ChunkedTransferDecoder.dataReceived} disregards chunk-extension
  929. fields.
  930. """
  931. L = []
  932. p = http._ChunkedTransferDecoder(L.append, None)
  933. p.dataReceived(b'3; x-foo=bar\r\nabc\r\n')
  934. self.assertEqual(L, [b'abc'])
  935. def test_finish(self):
  936. """
  937. L{_ChunkedTransferDecoder.dataReceived} interprets a zero-length
  938. chunk as the end of the chunked data stream and calls the completion
  939. callback.
  940. """
  941. finished = []
  942. p = http._ChunkedTransferDecoder(None, finished.append)
  943. p.dataReceived(b'0\r\n\r\n')
  944. self.assertEqual(finished, [b''])
  945. def test_extra(self):
  946. """
  947. L{_ChunkedTransferDecoder.dataReceived} passes any bytes which come
  948. after the terminating zero-length chunk to the completion callback.
  949. """
  950. finished = []
  951. p = http._ChunkedTransferDecoder(None, finished.append)
  952. p.dataReceived(b'0\r\n\r\nhello')
  953. self.assertEqual(finished, [b'hello'])
  954. def test_afterFinished(self):
  955. """
  956. L{_ChunkedTransferDecoder.dataReceived} raises C{RuntimeError} if it
  957. is called after it has seen the last chunk.
  958. """
  959. p = http._ChunkedTransferDecoder(None, lambda bytes: None)
  960. p.dataReceived(b'0\r\n\r\n')
  961. self.assertRaises(RuntimeError, p.dataReceived, b'hello')
  962. def test_earlyConnectionLose(self):
  963. """
  964. L{_ChunkedTransferDecoder.noMoreData} raises L{_DataLoss} if it is
  965. called and the end of the last trailer has not yet been received.
  966. """
  967. parser = http._ChunkedTransferDecoder(None, lambda bytes: None)
  968. parser.dataReceived(b'0\r\n\r')
  969. exc = self.assertRaises(_DataLoss, parser.noMoreData)
  970. self.assertEqual(
  971. str(exc),
  972. "Chunked decoder in 'TRAILER' state, still expecting more data "
  973. "to get to 'FINISHED' state.")
  974. def test_finishedConnectionLose(self):
  975. """
  976. L{_ChunkedTransferDecoder.noMoreData} does not raise any exception if
  977. it is called after the terminal zero length chunk is received.
  978. """
  979. parser = http._ChunkedTransferDecoder(None, lambda bytes: None)
  980. parser.dataReceived(b'0\r\n\r\n')
  981. parser.noMoreData()
  982. def test_reentrantFinishedNoMoreData(self):
  983. """
  984. L{_ChunkedTransferDecoder.noMoreData} can be called from the finished
  985. callback without raising an exception.
  986. """
  987. errors = []
  988. successes = []
  989. def finished(extra):
  990. try:
  991. parser.noMoreData()
  992. except:
  993. errors.append(Failure())
  994. else:
  995. successes.append(True)
  996. parser = http._ChunkedTransferDecoder(None, finished)
  997. parser.dataReceived(b'0\r\n\r\n')
  998. self.assertEqual(errors, [])
  999. self.assertEqual(successes, [True])
  1000. class ChunkingTests(unittest.TestCase, ResponseTestMixin):
  1001. strings = [b"abcv", b"", b"fdfsd423", b"Ffasfas\r\n",
  1002. b"523523\n\rfsdf", b"4234"]
  1003. def testChunks(self):
  1004. for s in self.strings:
  1005. chunked = b''.join(http.toChunk(s))
  1006. self.assertEqual((s, b''), http.fromChunk(chunked))
  1007. self.assertRaises(ValueError, http.fromChunk, b'-5\r\nmalformed!\r\n')
  1008. def testConcatenatedChunks(self):
  1009. chunked = b''.join([b''.join(http.toChunk(t)) for t in self.strings])
  1010. result = []
  1011. buffer = b""
  1012. for c in iterbytes(chunked):
  1013. buffer = buffer + c
  1014. try:
  1015. data, buffer = http.fromChunk(buffer)
  1016. result.append(data)
  1017. except ValueError:
  1018. pass
  1019. self.assertEqual(result, self.strings)
  1020. def test_chunkedResponses(self):
  1021. """
  1022. Test that the L{HTTPChannel} correctly chunks responses when needed.
  1023. """
  1024. channel = http.HTTPChannel()
  1025. req = http.Request(channel, False)
  1026. trans = StringTransport()
  1027. channel.transport = trans
  1028. req.setResponseCode(200)
  1029. req.clientproto = b"HTTP/1.1"
  1030. req.responseHeaders.setRawHeaders(b"test", [b"lemur"])
  1031. req.write(b'Hello')
  1032. req.write(b'World!')
  1033. self.assertResponseEquals(
  1034. trans.value(),
  1035. [(b"HTTP/1.1 200 OK",
  1036. b"Test: lemur",
  1037. b"Transfer-Encoding: chunked",
  1038. b"5\r\nHello\r\n6\r\nWorld!\r\n")])
  1039. class ParsingTests(unittest.TestCase):
  1040. """
  1041. Tests for protocol parsing in L{HTTPChannel}.
  1042. """
  1043. def setUp(self):
  1044. self.didRequest = False
  1045. def runRequest(self, httpRequest, requestFactory=None, success=True,
  1046. channel=None):
  1047. """
  1048. Execute a web request based on plain text content.
  1049. @param httpRequest: Content for the request which is processed.
  1050. @type httpRequest: C{bytes}
  1051. @param requestFactory: 2-argument callable returning a Request.
  1052. @type requestFactory: C{callable}
  1053. @param success: Value to compare against I{self.didRequest}.
  1054. @type success: C{bool}
  1055. @param channel: Channel instance over which the request is processed.
  1056. @type channel: L{HTTPChannel}
  1057. @return: Returns the channel used for processing the request.
  1058. @rtype: L{HTTPChannel}
  1059. """
  1060. if not channel:
  1061. channel = http.HTTPChannel()
  1062. if requestFactory:
  1063. channel.requestFactory = _makeRequestProxyFactory(requestFactory)
  1064. httpRequest = httpRequest.replace(b"\n", b"\r\n")
  1065. transport = StringTransport()
  1066. channel.makeConnection(transport)
  1067. # one byte at a time, to stress it.
  1068. for byte in iterbytes(httpRequest):
  1069. if channel.transport.disconnecting:
  1070. break
  1071. channel.dataReceived(byte)
  1072. channel.connectionLost(IOError("all done"))
  1073. if success:
  1074. self.assertTrue(self.didRequest)
  1075. else:
  1076. self.assertFalse(self.didRequest)
  1077. return channel
  1078. def test_invalidNonAsciiMethod(self):
  1079. """
  1080. When client sends invalid HTTP method containing
  1081. non-ascii characters HTTP 400 'Bad Request' status will be returned.
  1082. """
  1083. processed = []
  1084. class MyRequest(http.Request):
  1085. def process(self):
  1086. processed.append(self)
  1087. self.finish()
  1088. badRequestLine = b"GE\xc2\xa9 / HTTP/1.1\r\n\r\n"
  1089. channel = self.runRequest(badRequestLine, MyRequest, 0)
  1090. self.assertEqual(
  1091. channel.transport.value(),
  1092. b"HTTP/1.1 400 Bad Request\r\n\r\n")
  1093. self.assertTrue(channel.transport.disconnecting)
  1094. self.assertEqual(processed, [])
  1095. def test_basicAuth(self):
  1096. """
  1097. L{HTTPChannel} provides username and password information supplied in
  1098. an I{Authorization} header to the L{Request} which makes it available
  1099. via its C{getUser} and C{getPassword} methods.
  1100. """
  1101. requests = []
  1102. class Request(http.Request):
  1103. def process(self):
  1104. self.credentials = (self.getUser(), self.getPassword())
  1105. requests.append(self)
  1106. for u, p in [(b"foo", b"bar"), (b"hello", b"there:z")]:
  1107. s = base64.encodestring(b":".join((u, p))).strip()
  1108. f = b"GET / HTTP/1.0\nAuthorization: Basic " + s + b"\n\n"
  1109. self.runRequest(f, Request, 0)
  1110. req = requests.pop()
  1111. self.assertEqual((u, p), req.credentials)
  1112. def test_headers(self):
  1113. """
  1114. Headers received by L{HTTPChannel} in a request are made available to
  1115. the L{Request}.
  1116. """
  1117. processed = []
  1118. class MyRequest(http.Request):
  1119. def process(self):
  1120. processed.append(self)
  1121. self.finish()
  1122. requestLines = [
  1123. b"GET / HTTP/1.0",
  1124. b"Foo: bar",
  1125. b"baz: Quux",
  1126. b"baz: quux",
  1127. b"",
  1128. b""]
  1129. self.runRequest(b'\n'.join(requestLines), MyRequest, 0)
  1130. [request] = processed
  1131. self.assertEqual(
  1132. request.requestHeaders.getRawHeaders(b'foo'), [b'bar'])
  1133. self.assertEqual(
  1134. request.requestHeaders.getRawHeaders(b'bAz'), [b'Quux', b'quux'])
  1135. def test_tooManyHeaders(self):
  1136. """
  1137. L{HTTPChannel} enforces a limit of C{HTTPChannel.maxHeaders} on the
  1138. number of headers received per request.
  1139. """
  1140. processed = []
  1141. class MyRequest(http.Request):
  1142. def process(self):
  1143. processed.append(self)
  1144. requestLines = [b"GET / HTTP/1.0"]
  1145. for i in range(http.HTTPChannel.maxHeaders + 2):
  1146. requestLines.append(networkString("%s: foo" % (i,)))
  1147. requestLines.extend([b"", b""])
  1148. channel = self.runRequest(b"\n".join(requestLines), MyRequest, 0)
  1149. self.assertEqual(processed, [])
  1150. self.assertEqual(
  1151. channel.transport.value(),
  1152. b"HTTP/1.1 400 Bad Request\r\n\r\n")
  1153. def test_invalidContentLengthHeader(self):
  1154. """
  1155. If a Content-Length header with a non-integer value is received, a 400
  1156. (Bad Request) response is sent to the client and the connection is
  1157. closed.
  1158. """
  1159. processed = []
  1160. class MyRequest(http.Request):
  1161. def process(self):
  1162. processed.append(self)
  1163. self.finish()
  1164. requestLines = [b"GET / HTTP/1.0", b"Content-Length: x", b"", b""]
  1165. channel = self.runRequest(b"\n".join(requestLines), MyRequest, 0)
  1166. self.assertEqual(
  1167. channel.transport.value(),
  1168. b"HTTP/1.1 400 Bad Request\r\n\r\n")
  1169. self.assertTrue(channel.transport.disconnecting)
  1170. self.assertEqual(processed, [])
  1171. def test_invalidHeaderNoColon(self):
  1172. """
  1173. If a header without colon is received a 400 (Bad Request) response
  1174. is sent to the client and the connection is closed.
  1175. """
  1176. processed = []
  1177. class MyRequest(http.Request):
  1178. def process(self):
  1179. processed.append(self)
  1180. self.finish()
  1181. requestLines = [b"GET / HTTP/1.0", b"HeaderName ", b"", b""]
  1182. channel = self.runRequest(b"\n".join(requestLines), MyRequest, 0)
  1183. self.assertEqual(
  1184. channel.transport.value(),
  1185. b"HTTP/1.1 400 Bad Request\r\n\r\n")
  1186. self.assertTrue(channel.transport.disconnecting)
  1187. self.assertEqual(processed, [])
  1188. def test_headerLimitPerRequest(self):
  1189. """
  1190. L{HTTPChannel} enforces the limit of C{HTTPChannel.maxHeaders} per
  1191. request so that headers received in an earlier request do not count
  1192. towards the limit when processing a later request.
  1193. """
  1194. processed = []
  1195. class MyRequest(http.Request):
  1196. def process(self):
  1197. processed.append(self)
  1198. self.finish()
  1199. self.patch(http.HTTPChannel, 'maxHeaders', 1)
  1200. requestLines = [
  1201. b"GET / HTTP/1.1",
  1202. b"Foo: bar",
  1203. b"",
  1204. b"",
  1205. b"GET / HTTP/1.1",
  1206. b"Bar: baz",
  1207. b"",
  1208. b""]
  1209. channel = self.runRequest(b"\n".join(requestLines), MyRequest, 0)
  1210. [first, second] = processed
  1211. self.assertEqual(first.getHeader(b'foo'), b'bar')
  1212. self.assertEqual(second.getHeader(b'bar'), b'baz')
  1213. self.assertEqual(
  1214. channel.transport.value(),
  1215. b'HTTP/1.1 200 OK\r\n'
  1216. b'Transfer-Encoding: chunked\r\n'
  1217. b'\r\n'
  1218. b'0\r\n'
  1219. b'\r\n'
  1220. b'HTTP/1.1 200 OK\r\n'
  1221. b'Transfer-Encoding: chunked\r\n'
  1222. b'\r\n'
  1223. b'0\r\n'
  1224. b'\r\n')
  1225. def test_headersTooBigInitialCommand(self):
  1226. """
  1227. Enforces a limit of C{HTTPChannel.totalHeadersSize}
  1228. on the size of headers received per request starting from initial
  1229. command line.
  1230. """
  1231. processed = []
  1232. class MyRequest(http.Request):
  1233. def process(self):
  1234. processed.append(self)
  1235. self.finish()
  1236. channel = http.HTTPChannel()
  1237. channel.totalHeadersSize = 10
  1238. httpRequest = b'GET /path/longer/than/10 HTTP/1.1\n'
  1239. channel = self.runRequest(
  1240. httpRequest=httpRequest,
  1241. requestFactory=MyRequest,
  1242. channel=channel,
  1243. success=False
  1244. )
  1245. self.assertEqual(processed, [])
  1246. self.assertEqual(
  1247. channel.transport.value(),
  1248. b"HTTP/1.1 400 Bad Request\r\n\r\n")
  1249. def test_headersTooBigOtherHeaders(self):
  1250. """
  1251. Enforces a limit of C{HTTPChannel.totalHeadersSize}
  1252. on the size of headers received per request counting first line
  1253. and total headers.
  1254. """
  1255. processed = []
  1256. class MyRequest(http.Request):
  1257. def process(self):
  1258. processed.append(self)
  1259. self.finish()
  1260. channel = http.HTTPChannel()
  1261. channel.totalHeadersSize = 40
  1262. httpRequest = (
  1263. b'GET /less/than/40 HTTP/1.1\n'
  1264. b'Some-Header: less-than-40\n'
  1265. )
  1266. channel = self.runRequest(
  1267. httpRequest=httpRequest,
  1268. requestFactory=MyRequest,
  1269. channel=channel, success=False
  1270. )
  1271. self.assertEqual(processed, [])
  1272. self.assertEqual(
  1273. channel.transport.value(),
  1274. b"HTTP/1.1 400 Bad Request\r\n\r\n")
  1275. def test_headersTooBigPerRequest(self):
  1276. """
  1277. Enforces total size of headers per individual request and counter
  1278. is reset at the end of each request.
  1279. """
  1280. class SimpleRequest(http.Request):
  1281. def process(self):
  1282. self.finish()
  1283. channel = http.HTTPChannel()
  1284. channel.totalHeadersSize = 60
  1285. channel.requestFactory = SimpleRequest
  1286. httpRequest = (
  1287. b'GET / HTTP/1.1\n'
  1288. b'Some-Header: total-less-than-60\n'
  1289. b'\n'
  1290. b'GET / HTTP/1.1\n'
  1291. b'Some-Header: less-than-60\n'
  1292. b'\n'
  1293. )
  1294. channel = self.runRequest(
  1295. httpRequest=httpRequest, channel=channel, success=False)
  1296. self.assertEqual(
  1297. channel.transport.value(),
  1298. b'HTTP/1.1 200 OK\r\n'
  1299. b'Transfer-Encoding: chunked\r\n'
  1300. b'\r\n'
  1301. b'0\r\n'
  1302. b'\r\n'
  1303. b'HTTP/1.1 200 OK\r\n'
  1304. b'Transfer-Encoding: chunked\r\n'
  1305. b'\r\n'
  1306. b'0\r\n'
  1307. b'\r\n'
  1308. )
  1309. def testCookies(self):
  1310. """
  1311. Test cookies parsing and reading.
  1312. """
  1313. httpRequest = b'''\
  1314. GET / HTTP/1.0
  1315. Cookie: rabbit="eat carrot"; ninja=secret; spam="hey 1=1!"
  1316. '''
  1317. cookies = {}
  1318. testcase = self
  1319. class MyRequest(http.Request):
  1320. def process(self):
  1321. for name in [b'rabbit', b'ninja', b'spam']:
  1322. cookies[name] = self.getCookie(name)
  1323. testcase.didRequest = True
  1324. self.finish()
  1325. self.runRequest(httpRequest, MyRequest)
  1326. self.assertEqual(
  1327. cookies, {
  1328. b'rabbit': b'"eat carrot"',
  1329. b'ninja': b'secret',
  1330. b'spam': b'"hey 1=1!"'})
  1331. def testGET(self):
  1332. httpRequest = b'''\
  1333. GET /?key=value&multiple=two+words&multiple=more%20words&empty= HTTP/1.0
  1334. '''
  1335. method = []
  1336. args = []
  1337. testcase = self
  1338. class MyRequest(http.Request):
  1339. def process(self):
  1340. method.append(self.method)
  1341. args.extend([
  1342. self.args[b"key"],
  1343. self.args[b"empty"],
  1344. self.args[b"multiple"]])
  1345. testcase.didRequest = True
  1346. self.finish()
  1347. self.runRequest(httpRequest, MyRequest)
  1348. self.assertEqual(method, [b"GET"])
  1349. self.assertEqual(
  1350. args, [[b"value"], [b""], [b"two words", b"more words"]])
  1351. def test_extraQuestionMark(self):
  1352. """
  1353. While only a single '?' is allowed in an URL, several other servers
  1354. allow several and pass all after the first through as part of the
  1355. query arguments. Test that we emulate this behavior.
  1356. """
  1357. httpRequest = b'GET /foo?bar=?&baz=quux HTTP/1.0\n\n'
  1358. method = []
  1359. path = []
  1360. args = []
  1361. testcase = self
  1362. class MyRequest(http.Request):
  1363. def process(self):
  1364. method.append(self.method)
  1365. path.append(self.path)
  1366. args.extend([self.args[b'bar'], self.args[b'baz']])
  1367. testcase.didRequest = True
  1368. self.finish()
  1369. self.runRequest(httpRequest, MyRequest)
  1370. self.assertEqual(method, [b'GET'])
  1371. self.assertEqual(path, [b'/foo'])
  1372. self.assertEqual(args, [[b'?'], [b'quux']])
  1373. def test_formPOSTRequest(self):
  1374. """
  1375. The request body of a I{POST} request with a I{Content-Type} header
  1376. of I{application/x-www-form-urlencoded} is parsed according to that
  1377. content type and made available in the C{args} attribute of the
  1378. request object. The original bytes of the request may still be read
  1379. from the C{content} attribute.
  1380. """
  1381. query = 'key=value&multiple=two+words&multiple=more%20words&empty='
  1382. httpRequest = networkString('''\
  1383. POST / HTTP/1.0
  1384. Content-Length: %d
  1385. Content-Type: application/x-www-form-urlencoded
  1386. %s''' % (len(query), query))
  1387. method = []
  1388. args = []
  1389. content = []
  1390. testcase = self
  1391. class MyRequest(http.Request):
  1392. def process(self):
  1393. method.append(self.method)
  1394. args.extend([
  1395. self.args[b'key'], self.args[b'empty'],
  1396. self.args[b'multiple']])
  1397. content.append(self.content.read())
  1398. testcase.didRequest = True
  1399. self.finish()
  1400. self.runRequest(httpRequest, MyRequest)
  1401. self.assertEqual(method, [b"POST"])
  1402. self.assertEqual(
  1403. args, [[b"value"], [b""], [b"two words", b"more words"]])
  1404. # Reading from the content file-like must produce the entire request
  1405. # body.
  1406. self.assertEqual(content, [networkString(query)])
  1407. def test_missingContentDisposition(self):
  1408. """
  1409. If the C{Content-Disposition} header is missing, the request is denied
  1410. as a bad request.
  1411. """
  1412. req = b'''\
  1413. POST / HTTP/1.0
  1414. Content-Type: multipart/form-data; boundary=AaB03x
  1415. Content-Length: 103
  1416. --AaB03x
  1417. Content-Type: text/plain
  1418. Content-Transfer-Encoding: quoted-printable
  1419. abasdfg
  1420. --AaB03x--
  1421. '''
  1422. channel = self.runRequest(req, http.Request, success=False)
  1423. self.assertEqual(
  1424. channel.transport.value(),
  1425. b"HTTP/1.1 400 Bad Request\r\n\r\n")
  1426. if _PY3:
  1427. test_missingContentDisposition.skip = (
  1428. "cgi.parse_multipart is much more error-tolerant on Python 3.")
  1429. def test_multipartProcessingFailure(self):
  1430. """
  1431. When the multipart processing fails the client gets a 400 Bad Request.
  1432. """
  1433. # The parsing failure is simulated by having a Content-Length that
  1434. # doesn't fit in a ssize_t.
  1435. req = b'''\
  1436. POST / HTTP/1.0
  1437. Content-Type: multipart/form-data; boundary=AaB03x
  1438. Content-Length: 103
  1439. --AaB03x
  1440. Content-Type: text/plain
  1441. Content-Length: 999999999999999999999999999999999999999999999999999999999999999
  1442. Content-Transfer-Encoding: quoted-printable
  1443. abasdfg
  1444. --AaB03x--
  1445. '''
  1446. channel = self.runRequest(req, http.Request, success=False)
  1447. self.assertEqual(
  1448. channel.transport.value(),
  1449. b"HTTP/1.1 400 Bad Request\r\n\r\n")
  1450. def test_multipartFormData(self):
  1451. """
  1452. If the request has a Content-Type of C{multipart/form-data}, and the
  1453. form data is parseable, the form arguments will be added to the
  1454. request's args.
  1455. """
  1456. processed = []
  1457. class MyRequest(http.Request):
  1458. def process(self):
  1459. processed.append(self)
  1460. self.write(b"done")
  1461. self.finish()
  1462. req = b'''\
  1463. POST / HTTP/1.0
  1464. Content-Type: multipart/form-data; boundary=AaB03x
  1465. Content-Length: 149
  1466. --AaB03x
  1467. Content-Type: text/plain
  1468. Content-Disposition: form-data; name="text"
  1469. Content-Transfer-Encoding: quoted-printable
  1470. abasdfg
  1471. --AaB03x--
  1472. '''
  1473. channel = self.runRequest(req, MyRequest, success=False)
  1474. self.assertEqual(channel.transport.value(),
  1475. b"HTTP/1.0 200 OK\r\n\r\ndone")
  1476. self.assertEqual(len(processed), 1)
  1477. self.assertEqual(processed[0].args, {b"text": [b"abasdfg"]})
  1478. def test_chunkedEncoding(self):
  1479. """
  1480. If a request uses the I{chunked} transfer encoding, the request body is
  1481. decoded accordingly before it is made available on the request.
  1482. """
  1483. httpRequest = b'''\
  1484. GET / HTTP/1.0
  1485. Content-Type: text/plain
  1486. Transfer-Encoding: chunked
  1487. 6
  1488. Hello,
  1489. 14
  1490. spam,eggs spam spam
  1491. 0
  1492. '''
  1493. path = []
  1494. method = []
  1495. content = []
  1496. decoder = []
  1497. testcase = self
  1498. class MyRequest(http.Request):
  1499. def process(self):
  1500. content.append(self.content.fileno())
  1501. content.append(self.content.read())
  1502. method.append(self.method)
  1503. path.append(self.path)
  1504. decoder.append(self.channel._transferDecoder)
  1505. testcase.didRequest = True
  1506. self.finish()
  1507. self.runRequest(httpRequest, MyRequest)
  1508. # The tempfile API used to create content returns an
  1509. # instance of a different type depending on what platform
  1510. # we're running on. The point here is to verify that the
  1511. # request body is in a file that's on the filesystem.
  1512. # Having a fileno method that returns an int is a somewhat
  1513. # close approximation of this. -exarkun
  1514. self.assertIsInstance(content[0], int)
  1515. self.assertEqual(content[1], b'Hello, spam,eggs spam spam')
  1516. self.assertEqual(method, [b'GET'])
  1517. self.assertEqual(path, [b'/'])
  1518. self.assertEqual(decoder, [None])
  1519. def test_malformedChunkedEncoding(self):
  1520. """
  1521. If a request uses the I{chunked} transfer encoding, but provides an
  1522. invalid chunk length value, the request fails with a 400 error.
  1523. """
  1524. # See test_chunkedEncoding for the correct form of this request.
  1525. httpRequest = b'''\
  1526. GET / HTTP/1.1
  1527. Content-Type: text/plain
  1528. Transfer-Encoding: chunked
  1529. MALFORMED_LINE_THIS_SHOULD_BE_'6'
  1530. Hello,
  1531. 14
  1532. spam,eggs spam spam
  1533. 0
  1534. '''
  1535. didRequest = []
  1536. class MyRequest(http.Request):
  1537. def process(self):
  1538. # This request should fail, so this should never be called.
  1539. didRequest.append(True)
  1540. channel = self.runRequest(httpRequest, MyRequest, success=False)
  1541. self.assertFalse(didRequest, "Request.process called")
  1542. self.assertEqual(
  1543. channel.transport.value(),
  1544. b"HTTP/1.1 400 Bad Request\r\n\r\n")
  1545. self.assertTrue(channel.transport.disconnecting)
  1546. class QueryArgumentsTests(unittest.TestCase):
  1547. def testParseqs(self):
  1548. self.assertEqual(
  1549. cgi.parse_qs(b"a=b&d=c;+=f"),
  1550. http.parse_qs(b"a=b&d=c;+=f"))
  1551. self.assertRaises(
  1552. ValueError, http.parse_qs, b"blah", strict_parsing=True)
  1553. self.assertEqual(
  1554. cgi.parse_qs(b"a=&b=c", keep_blank_values=1),
  1555. http.parse_qs(b"a=&b=c", keep_blank_values=1))
  1556. self.assertEqual(
  1557. cgi.parse_qs(b"a=&b=c"),
  1558. http.parse_qs(b"a=&b=c"))
  1559. def test_urlparse(self):
  1560. """
  1561. For a given URL, L{http.urlparse} should behave the same as L{urlparse},
  1562. except it should always return C{bytes}, never text.
  1563. """
  1564. def urls():
  1565. for scheme in (b'http', b'https'):
  1566. for host in (b'example.com',):
  1567. for port in (None, 100):
  1568. for path in (b'', b'path'):
  1569. if port is not None:
  1570. host = host + b':' + networkString(str(port))
  1571. yield urlunsplit((scheme, host, path, b'', b''))
  1572. def assertSameParsing(url, decode):
  1573. """
  1574. Verify that C{url} is parsed into the same objects by both
  1575. L{http.urlparse} and L{urlparse}.
  1576. """
  1577. urlToStandardImplementation = url
  1578. if decode:
  1579. urlToStandardImplementation = url.decode('ascii')
  1580. # stdlib urlparse will give back whatever type we give it. To be
  1581. # able to compare the values meaningfully, if it gives back unicode,
  1582. # convert all the values to bytes.
  1583. standardResult = urlparse(urlToStandardImplementation)
  1584. if isinstance(standardResult.scheme, unicode):
  1585. # The choice of encoding is basically irrelevant. The values
  1586. # are all in ASCII. UTF-8 is, of course, the correct choice.
  1587. expected = (standardResult.scheme.encode('utf-8'),
  1588. standardResult.netloc.encode('utf-8'),
  1589. standardResult.path.encode('utf-8'),
  1590. standardResult.params.encode('utf-8'),
  1591. standardResult.query.encode('utf-8'),
  1592. standardResult.fragment.encode('utf-8'))
  1593. else:
  1594. expected = (standardResult.scheme,
  1595. standardResult.netloc,
  1596. standardResult.path,
  1597. standardResult.params,
  1598. standardResult.query,
  1599. standardResult.fragment)
  1600. scheme, netloc, path, params, query, fragment = http.urlparse(url)
  1601. self.assertEqual(
  1602. (scheme, netloc, path, params, query, fragment), expected)
  1603. self.assertIsInstance(scheme, bytes)
  1604. self.assertIsInstance(netloc, bytes)
  1605. self.assertIsInstance(path, bytes)
  1606. self.assertIsInstance(params, bytes)
  1607. self.assertIsInstance(query, bytes)
  1608. self.assertIsInstance(fragment, bytes)
  1609. # With caching, unicode then str
  1610. clear_cache()
  1611. for url in urls():
  1612. assertSameParsing(url, True)
  1613. assertSameParsing(url, False)
  1614. # With caching, str then unicode
  1615. clear_cache()
  1616. for url in urls():
  1617. assertSameParsing(url, False)
  1618. assertSameParsing(url, True)
  1619. # Without caching
  1620. for url in urls():
  1621. clear_cache()
  1622. assertSameParsing(url, True)
  1623. clear_cache()
  1624. assertSameParsing(url, False)
  1625. def test_urlparseRejectsUnicode(self):
  1626. """
  1627. L{http.urlparse} should reject unicode input early.
  1628. """
  1629. self.assertRaises(TypeError, http.urlparse, u'http://example.org/path')
  1630. class ClientDriver(http.HTTPClient):
  1631. def handleStatus(self, version, status, message):
  1632. self.version = version
  1633. self.status = status
  1634. self.message = message
  1635. class ClientStatusParsingTests(unittest.TestCase):
  1636. def testBaseline(self):
  1637. c = ClientDriver()
  1638. c.lineReceived(b'HTTP/1.0 201 foo')
  1639. self.assertEqual(c.version, b'HTTP/1.0')
  1640. self.assertEqual(c.status, b'201')
  1641. self.assertEqual(c.message, b'foo')
  1642. def testNoMessage(self):
  1643. c = ClientDriver()
  1644. c.lineReceived(b'HTTP/1.0 201')
  1645. self.assertEqual(c.version, b'HTTP/1.0')
  1646. self.assertEqual(c.status, b'201')
  1647. self.assertEqual(c.message, b'')
  1648. def testNoMessage_trailingSpace(self):
  1649. c = ClientDriver()
  1650. c.lineReceived(b'HTTP/1.0 201 ')
  1651. self.assertEqual(c.version, b'HTTP/1.0')
  1652. self.assertEqual(c.status, b'201')
  1653. self.assertEqual(c.message, b'')
  1654. class RequestTests(unittest.TestCase, ResponseTestMixin):
  1655. """
  1656. Tests for L{http.Request}
  1657. """
  1658. def _compatHeadersTest(self, oldName, newName):
  1659. """
  1660. Verify that each of two different attributes which are associated with
  1661. the same state properly reflect changes made through the other.
  1662. This is used to test that the C{headers}/C{responseHeaders} and
  1663. C{received_headers}/C{requestHeaders} pairs interact properly.
  1664. """
  1665. req = http.Request(DummyChannel(), False)
  1666. getattr(req, newName).setRawHeaders(b"test", [b"lemur"])
  1667. self.assertEqual(getattr(req, oldName)[b"test"], b"lemur")
  1668. setattr(req, oldName, {b"foo": b"bar"})
  1669. self.assertEqual(
  1670. list(getattr(req, newName).getAllRawHeaders()),
  1671. [(b"Foo", [b"bar"])])
  1672. setattr(req, newName, http_headers.Headers())
  1673. self.assertEqual(getattr(req, oldName), {})
  1674. def test_getHeader(self):
  1675. """
  1676. L{http.Request.getHeader} returns the value of the named request
  1677. header.
  1678. """
  1679. req = http.Request(DummyChannel(), False)
  1680. req.requestHeaders.setRawHeaders(b"test", [b"lemur"])
  1681. self.assertEqual(req.getHeader(b"test"), b"lemur")
  1682. def test_getHeaderReceivedMultiples(self):
  1683. """
  1684. When there are multiple values for a single request header,
  1685. L{http.Request.getHeader} returns the last value.
  1686. """
  1687. req = http.Request(DummyChannel(), False)
  1688. req.requestHeaders.setRawHeaders(b"test", [b"lemur", b"panda"])
  1689. self.assertEqual(req.getHeader(b"test"), b"panda")
  1690. def test_getHeaderNotFound(self):
  1691. """
  1692. L{http.Request.getHeader} returns L{None} when asked for the value of a
  1693. request header which is not present.
  1694. """
  1695. req = http.Request(DummyChannel(), False)
  1696. self.assertEqual(req.getHeader(b"test"), None)
  1697. def test_getAllHeaders(self):
  1698. """
  1699. L{http.Request.getAllheaders} returns a C{dict} mapping all request
  1700. header names to their corresponding values.
  1701. """
  1702. req = http.Request(DummyChannel(), False)
  1703. req.requestHeaders.setRawHeaders(b"test", [b"lemur"])
  1704. self.assertEqual(req.getAllHeaders(), {b"test": b"lemur"})
  1705. def test_getAllHeadersNoHeaders(self):
  1706. """
  1707. L{http.Request.getAllHeaders} returns an empty C{dict} if there are no
  1708. request headers.
  1709. """
  1710. req = http.Request(DummyChannel(), False)
  1711. self.assertEqual(req.getAllHeaders(), {})
  1712. def test_getAllHeadersMultipleHeaders(self):
  1713. """
  1714. When there are multiple values for a single request header,
  1715. L{http.Request.getAllHeaders} returns only the last value.
  1716. """
  1717. req = http.Request(DummyChannel(), False)
  1718. req.requestHeaders.setRawHeaders(b"test", [b"lemur", b"panda"])
  1719. self.assertEqual(req.getAllHeaders(), {b"test": b"panda"})
  1720. def test_setResponseCode(self):
  1721. """
  1722. L{http.Request.setResponseCode} takes a status code and causes it to be
  1723. used as the response status.
  1724. """
  1725. channel = DummyChannel()
  1726. req = http.Request(channel, False)
  1727. req.setResponseCode(201)
  1728. req.write(b'')
  1729. self.assertEqual(
  1730. channel.transport.written.getvalue().splitlines()[0],
  1731. b"(no clientproto yet) 201 Created")
  1732. def test_setResponseCodeAndMessage(self):
  1733. """
  1734. L{http.Request.setResponseCode} takes a status code and a message and
  1735. causes them to be used as the response status.
  1736. """
  1737. channel = DummyChannel()
  1738. req = http.Request(channel, False)
  1739. req.setResponseCode(202, b"happily accepted")
  1740. req.write(b'')
  1741. self.assertEqual(
  1742. channel.transport.written.getvalue().splitlines()[0],
  1743. b'(no clientproto yet) 202 happily accepted')
  1744. def test_setResponseCodeAndMessageNotBytes(self):
  1745. """
  1746. L{http.Request.setResponseCode} accepts C{bytes} for the message
  1747. parameter and raises L{TypeError} if passed anything else.
  1748. """
  1749. channel = DummyChannel()
  1750. req = http.Request(channel, False)
  1751. self.assertRaises(TypeError, req.setResponseCode,
  1752. 202, u"not happily accepted")
  1753. def test_setResponseCodeAcceptsIntegers(self):
  1754. """
  1755. L{http.Request.setResponseCode} accepts C{int} for the code parameter
  1756. and raises L{TypeError} if passed anything else.
  1757. """
  1758. req = http.Request(DummyChannel(), False)
  1759. req.setResponseCode(1)
  1760. self.assertRaises(TypeError, req.setResponseCode, "1")
  1761. def test_setResponseCodeAcceptsLongIntegers(self):
  1762. """
  1763. L{http.Request.setResponseCode} accepts C{long} for the code
  1764. parameter.
  1765. """
  1766. req = http.Request(DummyChannel(), False)
  1767. req.setResponseCode(long(1))
  1768. if _PY3:
  1769. test_setResponseCodeAcceptsLongIntegers.skip = (
  1770. "Python 3 has no separate long integer type.")
  1771. def test_setLastModifiedNeverSet(self):
  1772. """
  1773. When no previous value was set and no 'if-modified-since' value was
  1774. requested, L{http.Request.setLastModified} takes a timestamp in seconds
  1775. since the epoch and sets the request's lastModified attribute.
  1776. """
  1777. req = http.Request(DummyChannel(), False)
  1778. req.setLastModified(42)
  1779. self.assertEqual(req.lastModified, 42)
  1780. def test_setLastModifiedUpdate(self):
  1781. """
  1782. If the supplied timestamp is later than the lastModified attribute's
  1783. value, L{http.Request.setLastModified} updates the lastModifed
  1784. attribute.
  1785. """
  1786. req = http.Request(DummyChannel(), False)
  1787. req.setLastModified(0)
  1788. req.setLastModified(1)
  1789. self.assertEqual(req.lastModified, 1)
  1790. def test_setLastModifiedIgnore(self):
  1791. """
  1792. If the supplied timestamp occurs earlier than the current lastModified
  1793. attribute, L{http.Request.setLastModified} ignores it.
  1794. """
  1795. req = http.Request(DummyChannel(), False)
  1796. req.setLastModified(1)
  1797. req.setLastModified(0)
  1798. self.assertEqual(req.lastModified, 1)
  1799. def test_setLastModifiedCached(self):
  1800. """
  1801. If the resource is older than the if-modified-since date in the request
  1802. header, L{http.Request.setLastModified} returns L{http.CACHED}.
  1803. """
  1804. req = http.Request(DummyChannel(), False)
  1805. req.requestHeaders.setRawHeaders(
  1806. networkString('if-modified-since'),
  1807. [b'02 Jan 1970 00:00:00 GMT']
  1808. )
  1809. result = req.setLastModified(42)
  1810. self.assertEqual(result, http.CACHED)
  1811. def test_setLastModifiedNotCached(self):
  1812. """
  1813. If the resource is newer than the if-modified-since date in the request
  1814. header, L{http.Request.setLastModified} returns None
  1815. """
  1816. req = http.Request(DummyChannel(), False)
  1817. req.requestHeaders.setRawHeaders(
  1818. networkString('if-modified-since'),
  1819. [b'01 Jan 1970 00:00:00 GMT']
  1820. )
  1821. result = req.setLastModified(1000000)
  1822. self.assertEqual(result, None)
  1823. def test_setLastModifiedTwiceNotCached(self):
  1824. """
  1825. When L{http.Request.setLastModified} is called multiple times, the
  1826. highest supplied value is honored. If that value is higher than the
  1827. if-modified-since date in the request header, the method returns None.
  1828. """
  1829. req = http.Request(DummyChannel(), False)
  1830. req.requestHeaders.setRawHeaders(
  1831. networkString('if-modified-since'),
  1832. [b'01 Jan 1970 00:00:01 GMT']
  1833. )
  1834. req.setLastModified(1000000)
  1835. result = req.setLastModified(0)
  1836. self.assertEqual(result, None)
  1837. def test_setLastModifiedTwiceCached(self):
  1838. """
  1839. When L{http.Request.setLastModified} is called multiple times, the
  1840. highest supplied value is honored. If that value is lower than the
  1841. if-modified-since date in the request header, the method returns
  1842. L{http.CACHED}.
  1843. """
  1844. req = http.Request(DummyChannel(), False)
  1845. req.requestHeaders.setRawHeaders(
  1846. networkString('if-modified-since'),
  1847. [b'01 Jan 1999 00:00:01 GMT']
  1848. )
  1849. req.setLastModified(1)
  1850. result = req.setLastModified(0)
  1851. self.assertEqual(result, http.CACHED)
  1852. def test_setHost(self):
  1853. """
  1854. L{http.Request.setHost} sets the value of the host request header.
  1855. The port should not be added because it is the default.
  1856. """
  1857. req = http.Request(DummyChannel(), False)
  1858. req.setHost(b"example.com", 80)
  1859. self.assertEqual(
  1860. req.requestHeaders.getRawHeaders(b"host"), [b"example.com"])
  1861. def test_setHostSSL(self):
  1862. """
  1863. L{http.Request.setHost} sets the value of the host request header.
  1864. The port should not be added because it is the default.
  1865. """
  1866. d = DummyChannel()
  1867. d.transport = DummyChannel.SSL()
  1868. req = http.Request(d, False)
  1869. req.setHost(b"example.com", 443)
  1870. self.assertEqual(
  1871. req.requestHeaders.getRawHeaders(b"host"), [b"example.com"])
  1872. def test_setHostNonDefaultPort(self):
  1873. """
  1874. L{http.Request.setHost} sets the value of the host request header.
  1875. The port should be added because it is not the default.
  1876. """
  1877. req = http.Request(DummyChannel(), False)
  1878. req.setHost(b"example.com", 81)
  1879. self.assertEqual(
  1880. req.requestHeaders.getRawHeaders(b"host"), [b"example.com:81"])
  1881. def test_setHostSSLNonDefaultPort(self):
  1882. """
  1883. L{http.Request.setHost} sets the value of the host request header.
  1884. The port should be added because it is not the default.
  1885. """
  1886. d = DummyChannel()
  1887. d.transport = DummyChannel.SSL()
  1888. req = http.Request(d, False)
  1889. req.setHost(b"example.com", 81)
  1890. self.assertEqual(
  1891. req.requestHeaders.getRawHeaders(b"host"), [b"example.com:81"])
  1892. def test_setHeader(self):
  1893. """
  1894. L{http.Request.setHeader} sets the value of the given response header.
  1895. """
  1896. req = http.Request(DummyChannel(), False)
  1897. req.setHeader(b"test", b"lemur")
  1898. self.assertEqual(req.responseHeaders.getRawHeaders(b"test"), [b"lemur"])
  1899. def _checkCookie(self, expectedCookieValue, *args, **kwargs):
  1900. """
  1901. Call L{http.Request.setCookie} with C{*args} and C{**kwargs}, and check
  1902. that the cookie value is equal to C{expectedCookieValue}.
  1903. """
  1904. channel = DummyChannel()
  1905. req = http.Request(channel, False)
  1906. req.addCookie(*args, **kwargs)
  1907. self.assertEqual(req.cookies[0], expectedCookieValue)
  1908. # Write nothing to make it produce the headers
  1909. req.write(b"")
  1910. writtenLines = channel.transport.written.getvalue().split(b"\r\n")
  1911. # There should be one Set-Cookie header
  1912. setCookieLines = [x for x in writtenLines
  1913. if x.startswith(b"Set-Cookie")]
  1914. self.assertEqual(len(setCookieLines), 1)
  1915. self.assertEqual(setCookieLines[0],
  1916. b"Set-Cookie: " + expectedCookieValue)
  1917. def test_addCookieWithMinimumArgumentsUnicode(self):
  1918. """
  1919. L{http.Request.setCookie} adds a new cookie to be sent with the
  1920. response, and can be called with just a key and a value. L{unicode}
  1921. arguments are encoded using UTF-8.
  1922. """
  1923. expectedCookieValue = b"foo=bar"
  1924. self._checkCookie(expectedCookieValue, u"foo", u"bar")
  1925. def test_addCookieWithAllArgumentsUnicode(self):
  1926. """
  1927. L{http.Request.setCookie} adds a new cookie to be sent with the
  1928. response. L{unicode} arguments are encoded using UTF-8.
  1929. """
  1930. expectedCookieValue = (
  1931. b"foo=bar; Expires=Fri, 31 Dec 9999 23:59:59 GMT; "
  1932. b"Domain=.example.com; Path=/; Max-Age=31536000; "
  1933. b"Comment=test; Secure; HttpOnly")
  1934. self._checkCookie(expectedCookieValue,
  1935. u"foo", u"bar", expires=u"Fri, 31 Dec 9999 23:59:59 GMT",
  1936. domain=u".example.com", path=u"/", max_age=u"31536000",
  1937. comment=u"test", secure=True, httpOnly=True)
  1938. def test_addCookieWithMinimumArgumentsBytes(self):
  1939. """
  1940. L{http.Request.setCookie} adds a new cookie to be sent with the
  1941. response, and can be called with just a key and a value. L{bytes}
  1942. arguments are not decoded.
  1943. """
  1944. expectedCookieValue = b"foo=bar"
  1945. self._checkCookie(expectedCookieValue, b"foo", b"bar")
  1946. def test_addCookieWithAllArgumentsBytes(self):
  1947. """
  1948. L{http.Request.setCookie} adds a new cookie to be sent with the
  1949. response. L{bytes} arguments are not decoded.
  1950. """
  1951. expectedCookieValue = (
  1952. b"foo=bar; Expires=Fri, 31 Dec 9999 23:59:59 GMT; "
  1953. b"Domain=.example.com; Path=/; Max-Age=31536000; "
  1954. b"Comment=test; Secure; HttpOnly")
  1955. self._checkCookie(expectedCookieValue,
  1956. b"foo", b"bar", expires=b"Fri, 31 Dec 9999 23:59:59 GMT",
  1957. domain=b".example.com", path=b"/", max_age=b"31536000",
  1958. comment=b"test", secure=True, httpOnly=True)
  1959. def test_addCookieNonStringArgument(self):
  1960. """
  1961. L{http.Request.setCookie} will raise a L{DeprecationWarning} if
  1962. non-string (not L{bytes} or L{unicode}) arguments are given, and will
  1963. call C{str()} on it to preserve past behaviour.
  1964. """
  1965. expectedCookieValue = b"foo=10"
  1966. self._checkCookie(expectedCookieValue, b"foo", 10)
  1967. warnings = self.flushWarnings([self._checkCookie])
  1968. self.assertEqual(1, len(warnings))
  1969. self.assertEqual(warnings[0]['category'], DeprecationWarning)
  1970. self.assertEqual(
  1971. warnings[0]['message'],
  1972. "Passing non-bytes or non-unicode cookie arguments is "
  1973. "deprecated since Twisted 16.1.")
  1974. def test_firstWrite(self):
  1975. """
  1976. For an HTTP 1.0 request, L{http.Request.write} sends an HTTP 1.0
  1977. Response-Line and whatever response headers are set.
  1978. """
  1979. channel = DummyChannel()
  1980. req = http.Request(channel, False)
  1981. trans = StringTransport()
  1982. channel.transport = trans
  1983. req.setResponseCode(200)
  1984. req.clientproto = b"HTTP/1.0"
  1985. req.responseHeaders.setRawHeaders(b"test", [b"lemur"])
  1986. req.write(b'Hello')
  1987. self.assertResponseEquals(
  1988. trans.value(),
  1989. [(b"HTTP/1.0 200 OK",
  1990. b"Test: lemur",
  1991. b"Hello")])
  1992. def test_nonByteHeaderValue(self):
  1993. """
  1994. L{http.Request.write} casts non-bytes header value to bytes
  1995. transparently.
  1996. """
  1997. channel = DummyChannel()
  1998. req = http.Request(channel, False)
  1999. trans = StringTransport()
  2000. channel.transport = trans
  2001. req.setResponseCode(200)
  2002. req.clientproto = b"HTTP/1.0"
  2003. req.responseHeaders.setRawHeaders(b"test", [10])
  2004. req.write(b'Hello')
  2005. self.assertResponseEquals(
  2006. trans.value(),
  2007. [(b"HTTP/1.0 200 OK",
  2008. b"Test: 10",
  2009. b"Hello")])
  2010. warnings = self.flushWarnings(
  2011. offendingFunctions=[self.test_nonByteHeaderValue])
  2012. self.assertEqual(1, len(warnings))
  2013. self.assertEqual(warnings[0]['category'], DeprecationWarning)
  2014. self.assertEqual(
  2015. warnings[0]['message'],
  2016. "Passing non-bytes header values is deprecated since "
  2017. "Twisted 12.3. Pass only bytes instead.")
  2018. def test_firstWriteHTTP11Chunked(self):
  2019. """
  2020. For an HTTP 1.1 request, L{http.Request.write} sends an HTTP 1.1
  2021. Response-Line, whatever response headers are set, and uses chunked
  2022. encoding for the response body.
  2023. """
  2024. channel = DummyChannel()
  2025. req = http.Request(channel, False)
  2026. trans = StringTransport()
  2027. channel.transport = trans
  2028. req.setResponseCode(200)
  2029. req.clientproto = b"HTTP/1.1"
  2030. req.responseHeaders.setRawHeaders(b"test", [b"lemur"])
  2031. req.write(b'Hello')
  2032. req.write(b'World!')
  2033. self.assertResponseEquals(
  2034. trans.value(),
  2035. [(b"HTTP/1.1 200 OK",
  2036. b"Test: lemur",
  2037. b"Transfer-Encoding: chunked",
  2038. b"5\r\nHello\r\n6\r\nWorld!\r\n")])
  2039. def test_firstWriteLastModified(self):
  2040. """
  2041. For an HTTP 1.0 request for a resource with a known last modified time,
  2042. L{http.Request.write} sends an HTTP Response-Line, whatever response
  2043. headers are set, and a last-modified header with that time.
  2044. """
  2045. channel = DummyChannel()
  2046. req = http.Request(channel, False)
  2047. trans = StringTransport()
  2048. channel.transport = trans
  2049. req.setResponseCode(200)
  2050. req.clientproto = b"HTTP/1.0"
  2051. req.lastModified = 0
  2052. req.responseHeaders.setRawHeaders(b"test", [b"lemur"])
  2053. req.write(b'Hello')
  2054. self.assertResponseEquals(
  2055. trans.value(),
  2056. [(b"HTTP/1.0 200 OK",
  2057. b"Test: lemur",
  2058. b"Last-Modified: Thu, 01 Jan 1970 00:00:00 GMT",
  2059. b"Hello")])
  2060. def test_receivedCookiesDefault(self):
  2061. """
  2062. L{http.Request.received_cookies} defaults to an empty L{dict}.
  2063. """
  2064. req = http.Request(DummyChannel(), False)
  2065. self.assertEqual(req.received_cookies, {})
  2066. def test_parseCookies(self):
  2067. """
  2068. L{http.Request.parseCookies} extracts cookies from C{requestHeaders}
  2069. and adds them to C{received_cookies}.
  2070. """
  2071. req = http.Request(DummyChannel(), False)
  2072. req.requestHeaders.setRawHeaders(
  2073. b"cookie", [b'test="lemur"; test2="panda"'])
  2074. req.parseCookies()
  2075. self.assertEqual(
  2076. req.received_cookies, {b"test": b'"lemur"', b"test2": b'"panda"'})
  2077. def test_parseCookiesMultipleHeaders(self):
  2078. """
  2079. L{http.Request.parseCookies} can extract cookies from multiple Cookie
  2080. headers.
  2081. """
  2082. req = http.Request(DummyChannel(), False)
  2083. req.requestHeaders.setRawHeaders(
  2084. b"cookie", [b'test="lemur"', b'test2="panda"'])
  2085. req.parseCookies()
  2086. self.assertEqual(
  2087. req.received_cookies, {b"test": b'"lemur"', b"test2": b'"panda"'})
  2088. def test_parseCookiesNoCookie(self):
  2089. """
  2090. L{http.Request.parseCookies} can be called on a request without a
  2091. cookie header.
  2092. """
  2093. req = http.Request(DummyChannel(), False)
  2094. req.parseCookies()
  2095. self.assertEqual(req.received_cookies, {})
  2096. def test_parseCookiesEmptyCookie(self):
  2097. """
  2098. L{http.Request.parseCookies} can be called on a request with an
  2099. empty cookie header.
  2100. """
  2101. req = http.Request(DummyChannel(), False)
  2102. req.requestHeaders.setRawHeaders(
  2103. b"cookie", [])
  2104. req.parseCookies()
  2105. self.assertEqual(req.received_cookies, {})
  2106. def test_parseCookiesIgnoreValueless(self):
  2107. """
  2108. L{http.Request.parseCookies} ignores cookies which don't have a
  2109. value.
  2110. """
  2111. req = http.Request(DummyChannel(), False)
  2112. req.requestHeaders.setRawHeaders(
  2113. b"cookie", [b'foo; bar; baz;'])
  2114. req.parseCookies()
  2115. self.assertEqual(
  2116. req.received_cookies, {})
  2117. def test_parseCookiesEmptyValue(self):
  2118. """
  2119. L{http.Request.parseCookies} parses cookies with an empty value.
  2120. """
  2121. req = http.Request(DummyChannel(), False)
  2122. req.requestHeaders.setRawHeaders(
  2123. b"cookie", [b'foo='])
  2124. req.parseCookies()
  2125. self.assertEqual(
  2126. req.received_cookies, {b'foo': b''})
  2127. def test_parseCookiesRetainRightSpace(self):
  2128. """
  2129. L{http.Request.parseCookies} leaves trailing whitespace in the
  2130. cookie value.
  2131. """
  2132. req = http.Request(DummyChannel(), False)
  2133. req.requestHeaders.setRawHeaders(
  2134. b"cookie", [b'foo=bar '])
  2135. req.parseCookies()
  2136. self.assertEqual(
  2137. req.received_cookies, {b'foo': b'bar '})
  2138. def test_parseCookiesStripLeftSpace(self):
  2139. """
  2140. L{http.Request.parseCookies} strips leading whitespace in the
  2141. cookie key.
  2142. """
  2143. req = http.Request(DummyChannel(), False)
  2144. req.requestHeaders.setRawHeaders(
  2145. b"cookie", [b' foo=bar'])
  2146. req.parseCookies()
  2147. self.assertEqual(
  2148. req.received_cookies, {b'foo': b'bar'})
  2149. def test_parseCookiesContinueAfterMalformedCookie(self):
  2150. """
  2151. L{http.Request.parseCookies} parses valid cookies set before or
  2152. after malformed cookies.
  2153. """
  2154. req = http.Request(DummyChannel(), False)
  2155. req.requestHeaders.setRawHeaders(
  2156. b"cookie", [b'12345; test="lemur"; 12345; test2="panda"; 12345'])
  2157. req.parseCookies()
  2158. self.assertEqual(
  2159. req.received_cookies, {b"test": b'"lemur"', b"test2": b'"panda"'})
  2160. def test_connectionLost(self):
  2161. """
  2162. L{http.Request.connectionLost} closes L{Request.content} and drops the
  2163. reference to the L{HTTPChannel} to assist with garbage collection.
  2164. """
  2165. req = http.Request(DummyChannel(), False)
  2166. # Cause Request.content to be created at all.
  2167. req.gotLength(10)
  2168. # Grab a reference to content in case the Request drops it later on.
  2169. content = req.content
  2170. # Put some bytes into it
  2171. req.handleContentChunk(b"hello")
  2172. # Then something goes wrong and content should get closed.
  2173. req.connectionLost(Failure(ConnectionLost("Finished")))
  2174. self.assertTrue(content.closed)
  2175. self.assertIdentical(req.channel, None)
  2176. def test_registerProducerTwiceFails(self):
  2177. """
  2178. Calling L{Request.registerProducer} when a producer is already
  2179. registered raises ValueError.
  2180. """
  2181. req = http.Request(DummyChannel(), False)
  2182. req.registerProducer(DummyProducer(), True)
  2183. self.assertRaises(
  2184. ValueError, req.registerProducer, DummyProducer(), True)
  2185. def test_registerProducerWhenNotQueuedRegistersPushProducer(self):
  2186. """
  2187. Calling L{Request.registerProducer} with an IPushProducer when the
  2188. request is not queued registers the producer as a push producer on the
  2189. request's transport.
  2190. """
  2191. req = http.Request(DummyChannel(), False)
  2192. producer = DummyProducer()
  2193. req.registerProducer(producer, True)
  2194. self.assertEqual([(producer, True)], req.transport.producers)
  2195. def test_registerProducerWhenNotQueuedRegistersPullProducer(self):
  2196. """
  2197. Calling L{Request.registerProducer} with an IPullProducer when the
  2198. request is not queued registers the producer as a pull producer on the
  2199. request's transport.
  2200. """
  2201. req = http.Request(DummyChannel(), False)
  2202. producer = DummyProducer()
  2203. req.registerProducer(producer, False)
  2204. self.assertEqual([(producer, False)], req.transport.producers)
  2205. def test_connectionLostNotification(self):
  2206. """
  2207. L{Request.connectionLost} triggers all finish notification Deferreds
  2208. and cleans up per-request state.
  2209. """
  2210. d = DummyChannel()
  2211. request = http.Request(d, True)
  2212. finished = request.notifyFinish()
  2213. request.connectionLost(Failure(ConnectionLost("Connection done")))
  2214. self.assertIdentical(request.channel, None)
  2215. return self.assertFailure(finished, ConnectionLost)
  2216. def test_finishNotification(self):
  2217. """
  2218. L{Request.finish} triggers all finish notification Deferreds.
  2219. """
  2220. request = http.Request(DummyChannel(), False)
  2221. finished = request.notifyFinish()
  2222. # Force the request to have a non-None content attribute. This is
  2223. # probably a bug in Request.
  2224. request.gotLength(1)
  2225. request.finish()
  2226. return finished
  2227. def test_writeAfterFinish(self):
  2228. """
  2229. Calling L{Request.write} after L{Request.finish} has been called results
  2230. in a L{RuntimeError} being raised.
  2231. """
  2232. request = http.Request(DummyChannel(), False)
  2233. finished = request.notifyFinish()
  2234. # Force the request to have a non-None content attribute. This is
  2235. # probably a bug in Request.
  2236. request.gotLength(1)
  2237. request.write(b'foobar')
  2238. request.finish()
  2239. self.assertRaises(RuntimeError, request.write, b'foobar')
  2240. return finished
  2241. def test_finishAfterConnectionLost(self):
  2242. """
  2243. Calling L{Request.finish} after L{Request.connectionLost} has been
  2244. called results in a L{RuntimeError} being raised.
  2245. """
  2246. channel = DummyChannel()
  2247. req = http.Request(channel, False)
  2248. req.connectionLost(Failure(ConnectionLost("The end.")))
  2249. self.assertRaises(RuntimeError, req.finish)
  2250. def test_reprUninitialized(self):
  2251. """
  2252. L{Request.__repr__} returns the class name, object address, and
  2253. dummy-place holder values when used on a L{Request} which has not yet
  2254. been initialized.
  2255. """
  2256. request = http.Request(DummyChannel(), False)
  2257. self.assertEqual(
  2258. repr(request),
  2259. '<Request at 0x%x method=(no method yet) uri=(no uri yet) '
  2260. 'clientproto=(no clientproto yet)>' % (id(request),))
  2261. def test_reprInitialized(self):
  2262. """
  2263. L{Request.__repr__} returns, as a L{str}, the class name, object
  2264. address, and the method, uri, and client protocol of the HTTP request
  2265. it represents. The string is in the form::
  2266. <Request at ADDRESS method=METHOD uri=URI clientproto=PROTOCOL>
  2267. """
  2268. request = http.Request(DummyChannel(), False)
  2269. request.clientproto = b'HTTP/1.0'
  2270. request.method = b'GET'
  2271. request.uri = b'/foo/bar'
  2272. self.assertEqual(
  2273. repr(request),
  2274. '<Request at 0x%x method=GET uri=/foo/bar '
  2275. 'clientproto=HTTP/1.0>' % (id(request),))
  2276. def test_reprSubclass(self):
  2277. """
  2278. Subclasses of L{Request} inherit a C{__repr__} implementation which
  2279. includes the subclass's name in place of the string C{"Request"}.
  2280. """
  2281. class Otherwise(http.Request):
  2282. pass
  2283. request = Otherwise(DummyChannel(), False)
  2284. self.assertEqual(
  2285. repr(request),
  2286. '<Otherwise at 0x%x method=(no method yet) uri=(no uri yet) '
  2287. 'clientproto=(no clientproto yet)>' % (id(request),))
  2288. def test_unregisterNonQueuedNonStreamingProducer(self):
  2289. """
  2290. L{Request.unregisterProducer} unregisters a non-queued non-streaming
  2291. producer from the request and the request's transport.
  2292. """
  2293. req = http.Request(DummyChannel(), False)
  2294. req.transport = StringTransport()
  2295. req.registerProducer(DummyProducer(), False)
  2296. req.unregisterProducer()
  2297. self.assertEqual((None, None), (req.producer, req.transport.producer))
  2298. def test_unregisterNonQueuedStreamingProducer(self):
  2299. """
  2300. L{Request.unregisterProducer} unregisters a non-queued streaming
  2301. producer from the request and the request's transport.
  2302. """
  2303. req = http.Request(DummyChannel(), False)
  2304. req.transport = StringTransport()
  2305. req.registerProducer(DummyProducer(), True)
  2306. req.unregisterProducer()
  2307. self.assertEqual((None, None), (req.producer, req.transport.producer))
  2308. def test_finishProducesLog(self):
  2309. """
  2310. L{http.Request.finish} will call the channel's factory to produce a log
  2311. message.
  2312. """
  2313. factory = http.HTTPFactory()
  2314. factory.timeOut = None
  2315. factory._logDateTime = "sometime"
  2316. factory._logDateTimeCall = True
  2317. factory.startFactory()
  2318. factory.logFile = NativeStringIO()
  2319. proto = factory.buildProtocol(None)
  2320. val = [
  2321. b"GET /path HTTP/1.1\r\n",
  2322. b"\r\n\r\n"
  2323. ]
  2324. trans = StringTransport()
  2325. proto.makeConnection(trans)
  2326. for x in val:
  2327. proto.dataReceived(x)
  2328. proto._channel.requests[0].finish()
  2329. # A log message should be written out
  2330. self.assertIn('sometime "GET /path HTTP/1.1"',
  2331. factory.logFile.getvalue())
  2332. def test_requestBodyTimeoutFromFactory(self):
  2333. """
  2334. L{HTTPChannel} timeouts whenever data from a request body is not
  2335. delivered to it in time, even when it gets built from a L{HTTPFactory}.
  2336. """
  2337. clock = Clock()
  2338. factory = http.HTTPFactory(timeout=100, reactor=clock)
  2339. factory.startFactory()
  2340. protocol = factory.buildProtocol(None)
  2341. transport = StringTransport()
  2342. protocol = parametrizeTimeoutMixin(protocol, clock)
  2343. # Confirm that the timeout is what we think it is.
  2344. self.assertEqual(protocol.timeOut, 100)
  2345. protocol.makeConnection(transport)
  2346. protocol.dataReceived(b'POST / HTTP/1.0\r\nContent-Length: 2\r\n\r\n')
  2347. clock.advance(99)
  2348. self.assertFalse(transport.disconnecting)
  2349. clock.advance(2)
  2350. self.assertTrue(transport.disconnecting)
  2351. def test_finishCleansConnection(self):
  2352. """
  2353. L{http.Request.finish} will notify the channel that it is finished, and
  2354. will put the transport back in the producing state so that the reactor
  2355. can close the connection.
  2356. """
  2357. factory = http.HTTPFactory()
  2358. factory.timeOut = None
  2359. factory._logDateTime = "sometime"
  2360. factory._logDateTimeCall = True
  2361. factory.startFactory()
  2362. factory.logFile = NativeStringIO()
  2363. proto = factory.buildProtocol(None)
  2364. val = [
  2365. b"GET /path HTTP/1.1\r\n",
  2366. b"Connection: close\r\n",
  2367. b"\r\n\r\n"
  2368. ]
  2369. trans = StringTransport()
  2370. proto.makeConnection(trans)
  2371. self.assertEqual(trans.producerState, 'producing')
  2372. for x in val:
  2373. proto.dataReceived(x)
  2374. self.assertEqual(trans.producerState, 'paused')
  2375. proto._channel.requests[0].finish()
  2376. self.assertEqual(trans.producerState, 'producing')
  2377. def test_provides_IDeprecatedHTTPChannelToRequestInterface(self):
  2378. """
  2379. L{http.Request} provides
  2380. L{http._IDeprecatedHTTPChannelToRequestInterface}, which
  2381. defines the interface used by L{http.HTTPChannel}.
  2382. """
  2383. req = http.Request(DummyChannel(), False)
  2384. verifyObject(http._IDeprecatedHTTPChannelToRequestInterface, req)
  2385. def test_eq(self):
  2386. """
  2387. A L{http.Request} is equal to itself.
  2388. """
  2389. req = http.Request(DummyChannel(), False)
  2390. self.assertEqual(req, req)
  2391. def test_ne(self):
  2392. """
  2393. A L{http.Request} is not equal to another object.
  2394. """
  2395. req = http.Request(DummyChannel(), False)
  2396. self.assertNotEqual(req, http.Request(DummyChannel(), False))
  2397. def test_eqWithNonRequest(self):
  2398. """
  2399. A L{http.Request} on the left hand side of an equality
  2400. comparison to an instance that is not a L{http.Request} hands
  2401. the comparison off to that object's C{__eq__} implementation.
  2402. """
  2403. eqCalls = []
  2404. class _NotARequest(object):
  2405. def __eq__(self, other):
  2406. eqCalls.append(other)
  2407. return True
  2408. req = http.Request(DummyChannel(), False)
  2409. self.assertEqual(req, _NotARequest())
  2410. self.assertEqual(eqCalls, [req])
  2411. def test_neWithNonRequest(self):
  2412. """
  2413. A L{http.Request} on the left hand side of an inequality
  2414. comparison to an instance that is not a L{http.Request} hands
  2415. the comparison off to that object's C{__ne__} implementation.
  2416. """
  2417. eqCalls = []
  2418. class _NotARequest(object):
  2419. def __ne__(self, other):
  2420. eqCalls.append(other)
  2421. return True
  2422. req = http.Request(DummyChannel(), False)
  2423. self.assertNotEqual(req, _NotARequest())
  2424. self.assertEqual(eqCalls, [req])
  2425. class MultilineHeadersTests(unittest.TestCase):
  2426. """
  2427. Tests to exercise handling of multiline headers by L{HTTPClient}. RFCs 1945
  2428. (HTTP 1.0) and 2616 (HTTP 1.1) state that HTTP message header fields can
  2429. span multiple lines if each extra line is preceded by at least one space or
  2430. horizontal tab.
  2431. """
  2432. def setUp(self):
  2433. """
  2434. Initialize variables used to verify that the header-processing functions
  2435. are getting called.
  2436. """
  2437. self.handleHeaderCalled = False
  2438. self.handleEndHeadersCalled = False
  2439. # Dictionary of sample complete HTTP header key/value pairs, including
  2440. # multiline headers.
  2441. expectedHeaders = {b'Content-Length': b'10',
  2442. b'X-Multiline' : b'line-0\tline-1',
  2443. b'X-Multiline2' : b'line-2 line-3'}
  2444. def ourHandleHeader(self, key, val):
  2445. """
  2446. Dummy implementation of L{HTTPClient.handleHeader}.
  2447. """
  2448. self.handleHeaderCalled = True
  2449. self.assertEqual(val, self.expectedHeaders[key])
  2450. def ourHandleEndHeaders(self):
  2451. """
  2452. Dummy implementation of L{HTTPClient.handleEndHeaders}.
  2453. """
  2454. self.handleEndHeadersCalled = True
  2455. def test_extractHeader(self):
  2456. """
  2457. A header isn't processed by L{HTTPClient.extractHeader} until it is
  2458. confirmed in L{HTTPClient.lineReceived} that the header has been
  2459. received completely.
  2460. """
  2461. c = ClientDriver()
  2462. c.handleHeader = self.ourHandleHeader
  2463. c.handleEndHeaders = self.ourHandleEndHeaders
  2464. c.lineReceived(b'HTTP/1.0 201')
  2465. c.lineReceived(b'Content-Length: 10')
  2466. self.assertIdentical(c.length, None)
  2467. self.assertFalse(self.handleHeaderCalled)
  2468. self.assertFalse(self.handleEndHeadersCalled)
  2469. # Signal end of headers.
  2470. c.lineReceived(b'')
  2471. self.assertTrue(self.handleHeaderCalled)
  2472. self.assertTrue(self.handleEndHeadersCalled)
  2473. self.assertEqual(c.length, 10)
  2474. def test_noHeaders(self):
  2475. """
  2476. An HTTP request with no headers will not cause any calls to
  2477. L{handleHeader} but will cause L{handleEndHeaders} to be called on
  2478. L{HTTPClient} subclasses.
  2479. """
  2480. c = ClientDriver()
  2481. c.handleHeader = self.ourHandleHeader
  2482. c.handleEndHeaders = self.ourHandleEndHeaders
  2483. c.lineReceived(b'HTTP/1.0 201')
  2484. # Signal end of headers.
  2485. c.lineReceived(b'')
  2486. self.assertFalse(self.handleHeaderCalled)
  2487. self.assertTrue(self.handleEndHeadersCalled)
  2488. self.assertEqual(c.version, b'HTTP/1.0')
  2489. self.assertEqual(c.status, b'201')
  2490. def test_multilineHeaders(self):
  2491. """
  2492. L{HTTPClient} parses multiline headers by buffering header lines until
  2493. an empty line or a line that does not start with whitespace hits
  2494. lineReceived, confirming that the header has been received completely.
  2495. """
  2496. c = ClientDriver()
  2497. c.handleHeader = self.ourHandleHeader
  2498. c.handleEndHeaders = self.ourHandleEndHeaders
  2499. c.lineReceived(b'HTTP/1.0 201')
  2500. c.lineReceived(b'X-Multiline: line-0')
  2501. self.assertFalse(self.handleHeaderCalled)
  2502. # Start continuing line with a tab.
  2503. c.lineReceived(b'\tline-1')
  2504. c.lineReceived(b'X-Multiline2: line-2')
  2505. # The previous header must be complete, so now it can be processed.
  2506. self.assertTrue(self.handleHeaderCalled)
  2507. # Start continuing line with a space.
  2508. c.lineReceived(b' line-3')
  2509. c.lineReceived(b'Content-Length: 10')
  2510. # Signal end of headers.
  2511. c.lineReceived(b'')
  2512. self.assertTrue(self.handleEndHeadersCalled)
  2513. self.assertEqual(c.version, b'HTTP/1.0')
  2514. self.assertEqual(c.status, b'201')
  2515. self.assertEqual(c.length, 10)
  2516. class Expect100ContinueServerTests(unittest.TestCase, ResponseTestMixin):
  2517. """
  2518. Test that the HTTP server handles 'Expect: 100-continue' header correctly.
  2519. The tests in this class all assume a simplistic behavior where user code
  2520. cannot choose to deny a request. Once ticket #288 is implemented and user
  2521. code can run before the body of a POST is processed this should be
  2522. extended to support overriding this behavior.
  2523. """
  2524. def test_HTTP10(self):
  2525. """
  2526. HTTP/1.0 requests do not get 100-continue returned, even if 'Expect:
  2527. 100-continue' is included (RFC 2616 10.1.1).
  2528. """
  2529. transport = StringTransport()
  2530. channel = http.HTTPChannel()
  2531. channel.requestFactory = DummyHTTPHandlerProxy
  2532. channel.makeConnection(transport)
  2533. channel.dataReceived(b"GET / HTTP/1.0\r\n")
  2534. channel.dataReceived(b"Host: www.example.com\r\n")
  2535. channel.dataReceived(b"Content-Length: 3\r\n")
  2536. channel.dataReceived(b"Expect: 100-continue\r\n")
  2537. channel.dataReceived(b"\r\n")
  2538. self.assertEqual(transport.value(), b"")
  2539. channel.dataReceived(b"abc")
  2540. self.assertResponseEquals(
  2541. transport.value(),
  2542. [(b"HTTP/1.0 200 OK",
  2543. b"Command: GET",
  2544. b"Content-Length: 13",
  2545. b"Version: HTTP/1.0",
  2546. b"Request: /",
  2547. b"'''\n3\nabc'''\n")])
  2548. def test_expect100ContinueHeader(self):
  2549. """
  2550. If a HTTP/1.1 client sends a 'Expect: 100-continue' header, the server
  2551. responds with a 100 response code before handling the request body, if
  2552. any. The normal resource rendering code will then be called, which
  2553. will send an additional response code.
  2554. """
  2555. transport = StringTransport()
  2556. channel = http.HTTPChannel()
  2557. channel.requestFactory = DummyHTTPHandlerProxy
  2558. channel.makeConnection(transport)
  2559. channel.dataReceived(b"GET / HTTP/1.1\r\n")
  2560. channel.dataReceived(b"Host: www.example.com\r\n")
  2561. channel.dataReceived(b"Expect: 100-continue\r\n")
  2562. channel.dataReceived(b"Content-Length: 3\r\n")
  2563. # The 100 continue response is not sent until all headers are
  2564. # received:
  2565. self.assertEqual(transport.value(), b"")
  2566. channel.dataReceived(b"\r\n")
  2567. # The 100 continue response is sent *before* the body is even
  2568. # received:
  2569. self.assertEqual(transport.value(), b"HTTP/1.1 100 Continue\r\n\r\n")
  2570. channel.dataReceived(b"abc")
  2571. response = transport.value()
  2572. self.assertTrue(
  2573. response.startswith(b"HTTP/1.1 100 Continue\r\n\r\n"))
  2574. response = response[len(b"HTTP/1.1 100 Continue\r\n\r\n"):]
  2575. self.assertResponseEquals(
  2576. response,
  2577. [(b"HTTP/1.1 200 OK",
  2578. b"Command: GET",
  2579. b"Content-Length: 13",
  2580. b"Version: HTTP/1.1",
  2581. b"Request: /",
  2582. b"'''\n3\nabc'''\n")])
  2583. def sub(keys, d):
  2584. """
  2585. Create a new dict containing only a subset of the items of an existing
  2586. dict.
  2587. @param keys: An iterable of the keys which will be added (with values from
  2588. C{d}) to the result.
  2589. @param d: The existing L{dict} from which to copy items.
  2590. @return: The new L{dict} with keys given by C{keys} and values given by the
  2591. corresponding values in C{d}.
  2592. @rtype: L{dict}
  2593. """
  2594. return dict([(k, d[k]) for k in keys])
  2595. class DeprecatedRequestAttributesTests(unittest.TestCase):
  2596. """
  2597. Tests for deprecated attributes of L{twisted.web.http.Request}.
  2598. """
  2599. def test_getClient(self):
  2600. """
  2601. L{Request.getClient} is deprecated in favor of resolving the hostname
  2602. in application code.
  2603. """
  2604. channel = DummyChannel()
  2605. request = http.Request(channel, True)
  2606. request.gotLength(123)
  2607. request.requestReceived(b"GET", b"/", b"HTTP/1.1")
  2608. expected = channel.transport.getPeer().host
  2609. self.assertEqual(expected, request.getClient())
  2610. warnings = self.flushWarnings(
  2611. offendingFunctions=[self.test_getClient])
  2612. self.assertEqual({
  2613. "category": DeprecationWarning,
  2614. "message": (
  2615. "twisted.web.http.Request.getClient was deprecated "
  2616. "in Twisted 15.0.0; please use Twisted Names to "
  2617. "resolve hostnames instead")},
  2618. sub(["category", "message"], warnings[0]))
  2619. def test_noLongerQueued(self):
  2620. """
  2621. L{Request.noLongerQueued} is deprecated, as we no longer process
  2622. requests simultaneously.
  2623. """
  2624. channel = DummyChannel()
  2625. request = http.Request(channel)
  2626. request.noLongerQueued()
  2627. warnings = self.flushWarnings(
  2628. offendingFunctions=[self.test_noLongerQueued])
  2629. self.assertEqual(1, len(warnings))
  2630. self.assertEqual({
  2631. "category": DeprecationWarning,
  2632. "message": (
  2633. "twisted.web.http.Request.noLongerQueued was deprecated "
  2634. "in Twisted 16.3.0")},
  2635. sub(["category", "message"], warnings[0]))
  2636. class ChannelProductionTests(unittest.TestCase):
  2637. """
  2638. Tests for the way HTTPChannel manages backpressure.
  2639. """
  2640. request = (
  2641. b'GET / HTTP/1.1\r\n'
  2642. b'Host: localhost\r\n'
  2643. b'\r\n'
  2644. )
  2645. def buildChannelAndTransport(self, transport, requestFactory):
  2646. """
  2647. Setup a L{HTTPChannel} and a transport and associate them.
  2648. @param transport: A transport to back the L{HTTPChannel}
  2649. @param requestFactory: An object that can construct L{Request} objects.
  2650. @return: A tuple of the channel and the transport.
  2651. """
  2652. transport = transport
  2653. channel = http.HTTPChannel()
  2654. channel.requestFactory = _makeRequestProxyFactory(requestFactory)
  2655. channel.makeConnection(transport)
  2656. return channel, transport
  2657. def test_HTTPChannelIsAProducer(self):
  2658. """
  2659. L{HTTPChannel} registers itself as a producer with its transport when a
  2660. connection is made.
  2661. """
  2662. channel, transport = self.buildChannelAndTransport(
  2663. StringTransport(), DummyHTTPHandler
  2664. )
  2665. self.assertEqual(transport.producer, channel)
  2666. self.assertTrue(transport.streaming)
  2667. def test_HTTPChannelUnregistersSelfWhenCallingLoseConnection(self):
  2668. """
  2669. L{HTTPChannel} unregisters itself when it has loseConnection called.
  2670. """
  2671. channel, transport = self.buildChannelAndTransport(
  2672. StringTransport(), DummyHTTPHandler
  2673. )
  2674. channel.loseConnection()
  2675. self.assertIs(transport.producer, None)
  2676. self.assertIs(transport.streaming, None)
  2677. def test_HTTPChannelRejectsMultipleProducers(self):
  2678. """
  2679. If two producers are registered on a L{HTTPChannel} without the first
  2680. being unregistered, a L{RuntimeError} is thrown.
  2681. """
  2682. channel, transport = self.buildChannelAndTransport(
  2683. StringTransport(), DummyHTTPHandler
  2684. )
  2685. channel.registerProducer(DummyProducer(), True)
  2686. self.assertRaises(
  2687. RuntimeError, channel.registerProducer, DummyProducer(), True
  2688. )
  2689. def test_HTTPChannelCanUnregisterWithNoProducer(self):
  2690. """
  2691. If there is no producer, the L{HTTPChannel} can still have
  2692. C{unregisterProducer} called.
  2693. """
  2694. channel, transport = self.buildChannelAndTransport(
  2695. StringTransport(), DummyHTTPHandler
  2696. )
  2697. channel.unregisterProducer()
  2698. self.assertIs(channel._requestProducer, None)
  2699. def test_HTTPChannelStopWithNoRequestOutstanding(self):
  2700. """
  2701. If there is no request producer currently registered, C{stopProducing}
  2702. does nothing.
  2703. """
  2704. channel, transport = self.buildChannelAndTransport(
  2705. StringTransport(), DummyHTTPHandler
  2706. )
  2707. channel.unregisterProducer()
  2708. self.assertIs(channel._requestProducer, None)
  2709. def test_HTTPChannelStopRequestProducer(self):
  2710. """
  2711. If there is a request producer registered with L{HTTPChannel}, calling
  2712. C{stopProducing} causes that producer to be stopped as well.
  2713. """
  2714. channel, transport = self.buildChannelAndTransport(
  2715. StringTransport(), DelayedHTTPHandler
  2716. )
  2717. # Feed a request in to spawn a Request object, then grab it.
  2718. channel.dataReceived(self.request)
  2719. request = channel.requests[0].original
  2720. # Register a dummy producer.
  2721. producer = DummyProducer()
  2722. request.registerProducer(producer, True)
  2723. # The dummy producer is currently unpaused.
  2724. self.assertEqual(producer.events, [])
  2725. # The transport now stops production. This stops the request producer.
  2726. channel.stopProducing()
  2727. self.assertEqual(producer.events, ['stop'])
  2728. def test_HTTPChannelPropagatesProducingFromTransportToTransport(self):
  2729. """
  2730. When L{HTTPChannel} has C{pauseProducing} called on it by the transport
  2731. it will call C{pauseProducing} on the transport. When unpaused, the
  2732. L{HTTPChannel} will call C{resumeProducing} on its transport.
  2733. """
  2734. channel, transport = self.buildChannelAndTransport(
  2735. StringTransport(), DummyHTTPHandler
  2736. )
  2737. # The transport starts in producing state.
  2738. self.assertEqual(transport.producerState, 'producing')
  2739. # Pause producing. The transport should now be paused as well.
  2740. channel.pauseProducing()
  2741. self.assertEqual(transport.producerState, 'paused')
  2742. # Resume producing. The transport should be unpaused.
  2743. channel.resumeProducing()
  2744. self.assertEqual(transport.producerState, 'producing')
  2745. def test_HTTPChannelPropagatesPausedProductionToRequest(self):
  2746. """
  2747. If a L{Request} object has registered itself as a producer with a
  2748. L{HTTPChannel} object, and the L{HTTPChannel} object is paused, both
  2749. the transport and L{Request} objects get paused.
  2750. """
  2751. channel, transport = self.buildChannelAndTransport(
  2752. StringTransport(), DelayedHTTPHandler
  2753. )
  2754. # Feed a request in to spawn a Request object, then grab it.
  2755. channel.dataReceived(self.request)
  2756. request = channel.requests[0].original
  2757. # Register a dummy producer.
  2758. producer = DummyProducer()
  2759. request.registerProducer(producer, True)
  2760. # Note that the transport is paused while it waits for a response.
  2761. # The dummy producer, however, is unpaused.
  2762. self.assertEqual(transport.producerState, 'paused')
  2763. self.assertEqual(producer.events, [])
  2764. # The transport now pauses production. This causes the producer to be
  2765. # paused. The transport stays paused.
  2766. channel.pauseProducing()
  2767. self.assertEqual(transport.producerState, 'paused')
  2768. self.assertEqual(producer.events, ['pause'])
  2769. # The transport has become unblocked and resumes production. This
  2770. # unblocks the dummy producer, but leaves the transport blocked.
  2771. channel.resumeProducing()
  2772. self.assertEqual(transport.producerState, 'paused')
  2773. self.assertEqual(producer.events, ['pause', 'resume'])
  2774. # Unregister the producer and then complete the response. Because the
  2775. # channel is not paused, the transport now gets unpaused.
  2776. request.unregisterProducer()
  2777. request.delayedProcess()
  2778. self.assertEqual(transport.producerState, 'producing')
  2779. def test_HTTPChannelStaysPausedWhenRequestCompletes(self):
  2780. """
  2781. If a L{Request} object completes its response while the transport is
  2782. paused, the L{HTTPChannel} does not resume the transport.
  2783. """
  2784. channel, transport = self.buildChannelAndTransport(
  2785. StringTransport(), DelayedHTTPHandler
  2786. )
  2787. # Feed a request in to spawn a Request object, then grab it.
  2788. channel.dataReceived(self.request)
  2789. request = channel.requests[0].original
  2790. # Register a dummy producer.
  2791. producer = DummyProducer()
  2792. request.registerProducer(producer, True)
  2793. # Note that the transport is paused while it waits for a response.
  2794. # The dummy producer, however, is unpaused.
  2795. self.assertEqual(transport.producerState, 'paused')
  2796. self.assertEqual(producer.events, [])
  2797. # The transport now pauses production. This causes the producer to be
  2798. # paused. The transport stays paused.
  2799. channel.pauseProducing()
  2800. self.assertEqual(transport.producerState, 'paused')
  2801. self.assertEqual(producer.events, ['pause'])
  2802. # Unregister the producer and then complete the response. Because the
  2803. # channel is still paused, the transport stays paused
  2804. request.unregisterProducer()
  2805. request.delayedProcess()
  2806. self.assertEqual(transport.producerState, 'paused')
  2807. # At this point the channel is resumed, and so is the transport.
  2808. channel.resumeProducing()
  2809. self.assertEqual(transport.producerState, 'producing')
  2810. def test_HTTPChannelToleratesDataWhenTransportPaused(self):
  2811. """
  2812. If the L{HTTPChannel} has paused the transport, it still tolerates
  2813. receiving data, and does not attempt to pause the transport again.
  2814. """
  2815. class NoDoublePauseTransport(StringTransport):
  2816. """
  2817. A version of L{StringTransport} that fails tests if it is paused
  2818. while already paused.
  2819. """
  2820. def pauseProducing(self):
  2821. if self.producerState == 'paused':
  2822. raise RuntimeError("Transport was paused twice!")
  2823. StringTransport.pauseProducing(self)
  2824. # Confirm that pausing a NoDoublePauseTransport twice fails.
  2825. transport = NoDoublePauseTransport()
  2826. transport.pauseProducing()
  2827. self.assertRaises(RuntimeError, transport.pauseProducing)
  2828. channel, transport = self.buildChannelAndTransport(
  2829. NoDoublePauseTransport(), DummyHTTPHandler
  2830. )
  2831. # The transport starts in producing state.
  2832. self.assertEqual(transport.producerState, 'producing')
  2833. # Pause producing. The transport should now be paused as well.
  2834. channel.pauseProducing()
  2835. self.assertEqual(transport.producerState, 'paused')
  2836. # Write in a request, even though the transport is paused.
  2837. channel.dataReceived(self.request)
  2838. # The transport is still paused, but we have tried to write the
  2839. # response out.
  2840. self.assertEqual(transport.producerState, 'paused')
  2841. self.assertTrue(transport.value().startswith(b'HTTP/1.1 200 OK\r\n'))
  2842. # Resume producing. The transport should be unpaused.
  2843. channel.resumeProducing()
  2844. self.assertEqual(transport.producerState, 'producing')
  2845. def test_HTTPChannelToleratesPullProducers(self):
  2846. """
  2847. If the L{HTTPChannel} has a L{IPullProducer} registered with it it can
  2848. adapt that producer into an L{IPushProducer}.
  2849. """
  2850. channel, transport = self.buildChannelAndTransport(
  2851. StringTransport(), DummyPullProducerHandler
  2852. )
  2853. transport = StringTransport()
  2854. channel = http.HTTPChannel()
  2855. channel.requestFactory = DummyPullProducerHandlerProxy
  2856. channel.makeConnection(transport)
  2857. channel.dataReceived(self.request)
  2858. request = channel.requests[0].original
  2859. responseComplete = request._actualProducer.result
  2860. def validate(ign):
  2861. responseBody = transport.value().split(b'\r\n\r\n', 1)[1]
  2862. expectedResponseBody = (
  2863. b'1\r\n0\r\n'
  2864. b'1\r\n1\r\n'
  2865. b'1\r\n2\r\n'
  2866. b'1\r\n3\r\n'
  2867. b'1\r\n4\r\n'
  2868. b'1\r\n5\r\n'
  2869. b'1\r\n6\r\n'
  2870. b'1\r\n7\r\n'
  2871. b'1\r\n8\r\n'
  2872. b'1\r\n9\r\n'
  2873. )
  2874. self.assertEqual(responseBody, expectedResponseBody)
  2875. return responseComplete.addCallback(validate)
  2876. def test_HTTPChannelUnregistersSelfWhenTimingOut(self):
  2877. """
  2878. L{HTTPChannel} unregisters itself when it times out a connection.
  2879. """
  2880. clock = Clock()
  2881. transport = StringTransport()
  2882. channel = http.HTTPChannel()
  2883. # Patch the channel's callLater method.
  2884. channel.timeOut = 100
  2885. channel.callLater = clock.callLater
  2886. channel.makeConnection(transport)
  2887. # Tick the clock forward almost to the timeout.
  2888. clock.advance(99)
  2889. self.assertIs(transport.producer, channel)
  2890. self.assertIs(transport.streaming, True)
  2891. # Fire the timeout.
  2892. clock.advance(1)
  2893. self.assertIs(transport.producer, None)
  2894. self.assertIs(transport.streaming, None)