test_newclient.py 102 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885
  1. # Copyright (c) Twisted Matrix Laboratories.
  2. # See LICENSE for details.
  3. """
  4. Tests for L{twisted.web._newclient}.
  5. """
  6. from __future__ import division, absolute_import
  7. __metaclass__ = type
  8. from zope.interface import implementer
  9. from zope.interface.verify import verifyObject
  10. from twisted.python import log
  11. from twisted.python.failure import Failure
  12. from twisted.internet.interfaces import IConsumer, IPushProducer
  13. from twisted.internet.error import ConnectionDone, ConnectionLost
  14. from twisted.internet.defer import Deferred, succeed, fail, CancelledError
  15. from twisted.internet.protocol import Protocol
  16. from twisted.trial.unittest import TestCase
  17. from twisted.test.proto_helpers import StringTransport, AccumulatingProtocol
  18. from twisted.web._newclient import UNKNOWN_LENGTH, STATUS, HEADER, BODY, DONE
  19. from twisted.web._newclient import HTTPParser, HTTPClientParser
  20. from twisted.web._newclient import BadResponseVersion, ParseError
  21. from twisted.web._newclient import ChunkedEncoder
  22. from twisted.web._newclient import WrongBodyLength, RequestNotSent
  23. from twisted.web._newclient import ConnectionAborted
  24. from twisted.web._newclient import BadHeaders, ExcessWrite
  25. from twisted.web._newclient import TransportProxyProducer, LengthEnforcingConsumer, makeStatefulDispatcher
  26. from twisted.web.client import (
  27. HTTP11ClientProtocol,
  28. PotentialDataLoss,
  29. Request,
  30. RequestGenerationFailed,
  31. RequestTransmissionFailed,
  32. Response,
  33. ResponseDone,
  34. ResponseFailed,
  35. ResponseNeverReceived,
  36. )
  37. from twisted.web.http_headers import Headers
  38. from twisted.web.http import _DataLoss
  39. from twisted.web.iweb import IBodyProducer, IResponse
  40. class StringTransport(StringTransport):
  41. """
  42. A version of C{StringTransport} that supports C{abortConnection}.
  43. """
  44. aborting = False
  45. def abortConnection(self):
  46. """
  47. A testable version of the C{ITCPTransport.abortConnection} method.
  48. Since this is a special case of closing the connection,
  49. C{loseConnection} is also called.
  50. """
  51. self.aborting = True
  52. self.loseConnection()
  53. class ArbitraryException(Exception):
  54. """
  55. A unique, arbitrary exception type which L{twisted.web._newclient} knows
  56. nothing about.
  57. """
  58. class AnotherArbitraryException(Exception):
  59. """
  60. Similar to L{ArbitraryException} but with a different identity.
  61. """
  62. # A re-usable Headers instance for tests which don't really care what headers
  63. # they're sending.
  64. _boringHeaders = Headers({b'host': [b'example.com']})
  65. def assertWrapperExceptionTypes(self, deferred, mainType, reasonTypes):
  66. """
  67. Assert that the given L{Deferred} fails with the exception given by
  68. C{mainType} and that the exceptions wrapped by the instance of C{mainType}
  69. it fails with match the list of exception types given by C{reasonTypes}.
  70. This is a helper for testing failures of exceptions which subclass
  71. L{_newclient._WrapperException}.
  72. @param self: A L{TestCase} instance which will be used to make the
  73. assertions.
  74. @param deferred: The L{Deferred} which is expected to fail with
  75. C{mainType}.
  76. @param mainType: A L{_newclient._WrapperException} subclass which will be
  77. trapped on C{deferred}.
  78. @param reasonTypes: A sequence of exception types which will be trapped on
  79. the resulting C{mainType} exception instance's C{reasons} sequence.
  80. @return: A L{Deferred} which fires with the C{mainType} instance
  81. C{deferred} fails with, or which fails somehow.
  82. """
  83. def cbFailed(err):
  84. for reason, type in zip(err.reasons, reasonTypes):
  85. reason.trap(type)
  86. self.assertEqual(len(err.reasons), len(reasonTypes),
  87. "len(%s) != len(%s)" % (err.reasons, reasonTypes))
  88. return err
  89. d = self.assertFailure(deferred, mainType)
  90. d.addCallback(cbFailed)
  91. return d
  92. def assertResponseFailed(self, deferred, reasonTypes):
  93. """
  94. A simple helper to invoke L{assertWrapperExceptionTypes} with a C{mainType}
  95. of L{ResponseFailed}.
  96. """
  97. return assertWrapperExceptionTypes(self, deferred, ResponseFailed, reasonTypes)
  98. def assertRequestGenerationFailed(self, deferred, reasonTypes):
  99. """
  100. A simple helper to invoke L{assertWrapperExceptionTypes} with a C{mainType}
  101. of L{RequestGenerationFailed}.
  102. """
  103. return assertWrapperExceptionTypes(self, deferred, RequestGenerationFailed, reasonTypes)
  104. def assertRequestTransmissionFailed(self, deferred, reasonTypes):
  105. """
  106. A simple helper to invoke L{assertWrapperExceptionTypes} with a C{mainType}
  107. of L{RequestTransmissionFailed}.
  108. """
  109. return assertWrapperExceptionTypes(self, deferred, RequestTransmissionFailed, reasonTypes)
  110. def justTransportResponse(transport):
  111. """
  112. Helper function for creating a Response which uses the given transport.
  113. All of the other parameters to L{Response.__init__} are filled with
  114. arbitrary values. Only use this method if you don't care about any of
  115. them.
  116. """
  117. return Response((b'HTTP', 1, 1), 200, b'OK', _boringHeaders, transport)
  118. class MakeStatefulDispatcherTests(TestCase):
  119. """
  120. Tests for L{makeStatefulDispatcher}.
  121. """
  122. def test_functionCalledByState(self):
  123. """
  124. A method defined with L{makeStatefulDispatcher} invokes a second
  125. method based on the current state of the object.
  126. """
  127. class Foo:
  128. _state = 'A'
  129. def bar(self):
  130. pass
  131. bar = makeStatefulDispatcher('quux', bar)
  132. def _quux_A(self):
  133. return 'a'
  134. def _quux_B(self):
  135. return 'b'
  136. stateful = Foo()
  137. self.assertEqual(stateful.bar(), 'a')
  138. stateful._state = 'B'
  139. self.assertEqual(stateful.bar(), 'b')
  140. stateful._state = 'C'
  141. self.assertRaises(RuntimeError, stateful.bar)
  142. class _HTTPParserTests(object):
  143. """
  144. Base test class for L{HTTPParser} which is responsible for the bulk of
  145. the task of parsing HTTP bytes.
  146. """
  147. sep = None
  148. def test_statusCallback(self):
  149. """
  150. L{HTTPParser} calls its C{statusReceived} method when it receives a
  151. status line.
  152. """
  153. status = []
  154. protocol = HTTPParser()
  155. protocol.statusReceived = status.append
  156. protocol.makeConnection(StringTransport())
  157. self.assertEqual(protocol.state, STATUS)
  158. protocol.dataReceived(b'HTTP/1.1 200 OK' + self.sep)
  159. self.assertEqual(status, [b'HTTP/1.1 200 OK'])
  160. self.assertEqual(protocol.state, HEADER)
  161. def _headerTestSetup(self):
  162. header = {}
  163. protocol = HTTPParser()
  164. protocol.headerReceived = header.__setitem__
  165. protocol.makeConnection(StringTransport())
  166. protocol.dataReceived(b'HTTP/1.1 200 OK' + self.sep)
  167. return header, protocol
  168. def test_headerCallback(self):
  169. """
  170. L{HTTPParser} calls its C{headerReceived} method when it receives a
  171. header.
  172. """
  173. header, protocol = self._headerTestSetup()
  174. protocol.dataReceived(b'X-Foo:bar' + self.sep)
  175. # Cannot tell it's not a continue header until the next line arrives
  176. # and is not a continuation
  177. protocol.dataReceived(self.sep)
  178. self.assertEqual(header, {b'X-Foo': b'bar'})
  179. self.assertEqual(protocol.state, BODY)
  180. def test_continuedHeaderCallback(self):
  181. """
  182. If a header is split over multiple lines, L{HTTPParser} calls
  183. C{headerReceived} with the entire value once it is received.
  184. """
  185. header, protocol = self._headerTestSetup()
  186. protocol.dataReceived(b'X-Foo: bar' + self.sep)
  187. protocol.dataReceived(b' baz' + self.sep)
  188. protocol.dataReceived(b'\tquux' + self.sep)
  189. protocol.dataReceived(self.sep)
  190. self.assertEqual(header, {b'X-Foo': b'bar baz\tquux'})
  191. self.assertEqual(protocol.state, BODY)
  192. def test_fieldContentWhitespace(self):
  193. """
  194. Leading and trailing linear whitespace is stripped from the header
  195. value passed to the C{headerReceived} callback.
  196. """
  197. header, protocol = self._headerTestSetup()
  198. value = self.sep.join([b' \t ', b' bar \t', b' \t', b''])
  199. protocol.dataReceived(b'X-Bar:' + value)
  200. protocol.dataReceived(b'X-Foo:' + value)
  201. protocol.dataReceived(self.sep)
  202. self.assertEqual(header, {b'X-Foo': b'bar',
  203. b'X-Bar': b'bar'})
  204. def test_allHeadersCallback(self):
  205. """
  206. After the last header is received, L{HTTPParser} calls
  207. C{allHeadersReceived}.
  208. """
  209. called = []
  210. header, protocol = self._headerTestSetup()
  211. def allHeadersReceived():
  212. called.append(protocol.state)
  213. protocol.state = STATUS
  214. protocol.allHeadersReceived = allHeadersReceived
  215. protocol.dataReceived(self.sep)
  216. self.assertEqual(called, [HEADER])
  217. self.assertEqual(protocol.state, STATUS)
  218. def test_noHeaderCallback(self):
  219. """
  220. If there are no headers in the message, L{HTTPParser} does not call
  221. C{headerReceived}.
  222. """
  223. header, protocol = self._headerTestSetup()
  224. protocol.dataReceived(self.sep)
  225. self.assertEqual(header, {})
  226. self.assertEqual(protocol.state, BODY)
  227. def test_headersSavedOnResponse(self):
  228. """
  229. All headers received by L{HTTPParser} are added to
  230. L{HTTPParser.headers}.
  231. """
  232. protocol = HTTPParser()
  233. protocol.makeConnection(StringTransport())
  234. protocol.dataReceived(b'HTTP/1.1 200 OK' + self.sep)
  235. protocol.dataReceived(b'X-Foo: bar' + self.sep)
  236. protocol.dataReceived(b'X-Foo: baz' + self.sep)
  237. protocol.dataReceived(self.sep)
  238. expected = [(b'X-Foo', [b'bar', b'baz'])]
  239. self.assertEqual(expected, list(protocol.headers.getAllRawHeaders()))
  240. def test_connectionControlHeaders(self):
  241. """
  242. L{HTTPParser.isConnectionControlHeader} returns C{True} for headers
  243. which are always connection control headers (similar to "hop-by-hop"
  244. headers from RFC 2616 section 13.5.1) and C{False} for other headers.
  245. """
  246. protocol = HTTPParser()
  247. connHeaderNames = [
  248. b'content-length', b'connection', b'keep-alive', b'te', b'trailers',
  249. b'transfer-encoding', b'upgrade', b'proxy-connection']
  250. for header in connHeaderNames:
  251. self.assertTrue(
  252. protocol.isConnectionControlHeader(header),
  253. "Expecting %r to be a connection control header, but "
  254. "wasn't" % (header,))
  255. self.assertFalse(
  256. protocol.isConnectionControlHeader(b"date"),
  257. "Expecting the arbitrarily selected 'date' header to not be "
  258. "a connection control header, but was.")
  259. def test_switchToBodyMode(self):
  260. """
  261. L{HTTPParser.switchToBodyMode} raises L{RuntimeError} if called more
  262. than once.
  263. """
  264. protocol = HTTPParser()
  265. protocol.makeConnection(StringTransport())
  266. protocol.switchToBodyMode(object())
  267. self.assertRaises(RuntimeError, protocol.switchToBodyMode, object())
  268. class HTTPParserRFCComplaintDelimeterTests(_HTTPParserTests, TestCase):
  269. """
  270. L{_HTTPParserTests} using standard CR LF newlines.
  271. """
  272. sep = b'\r\n'
  273. class HTTPParserNonRFCComplaintDelimeterTests(_HTTPParserTests, TestCase):
  274. """
  275. L{_HTTPParserTests} using bare LF newlines.
  276. """
  277. sep = b'\n'
  278. class HTTPClientParserTests(TestCase):
  279. """
  280. Tests for L{HTTPClientParser} which is responsible for parsing HTTP
  281. response messages.
  282. """
  283. def test_parseVersion(self):
  284. """
  285. L{HTTPClientParser.parseVersion} parses a status line into its three
  286. components.
  287. """
  288. protocol = HTTPClientParser(None, None)
  289. self.assertEqual(
  290. protocol.parseVersion(b'CANDY/7.2'),
  291. (b'CANDY', 7, 2))
  292. def test_parseBadVersion(self):
  293. """
  294. L{HTTPClientParser.parseVersion} raises L{ValueError} when passed an
  295. unparsable version.
  296. """
  297. protocol = HTTPClientParser(None, None)
  298. e = BadResponseVersion
  299. f = protocol.parseVersion
  300. def checkParsing(s):
  301. exc = self.assertRaises(e, f, s)
  302. self.assertEqual(exc.data, s)
  303. checkParsing(b'foo')
  304. checkParsing(b'foo/bar/baz')
  305. checkParsing(b'foo/')
  306. checkParsing(b'foo/..')
  307. checkParsing(b'foo/a.b')
  308. checkParsing(b'foo/-1.-1')
  309. def test_responseStatusParsing(self):
  310. """
  311. L{HTTPClientParser.statusReceived} parses the version, code, and phrase
  312. from the status line and stores them on the response object.
  313. """
  314. request = Request(b'GET', b'/', _boringHeaders, None)
  315. protocol = HTTPClientParser(request, None)
  316. protocol.makeConnection(StringTransport())
  317. protocol.dataReceived(b'HTTP/1.1 200 OK\r\n')
  318. self.assertEqual(protocol.response.version, (b'HTTP', 1, 1))
  319. self.assertEqual(protocol.response.code, 200)
  320. self.assertEqual(protocol.response.phrase, b'OK')
  321. def test_responseStatusWithoutPhrase(self):
  322. """
  323. L{HTTPClientParser.statusReceived} can parse a status line without a
  324. phrase (though such lines are a violation of RFC 7230, section 3.1.2;
  325. nevertheless some broken servers omit the phrase).
  326. """
  327. request = Request(b'GET', b'/', _boringHeaders, None)
  328. protocol = HTTPClientParser(request, None)
  329. protocol.makeConnection(StringTransport())
  330. protocol.dataReceived(b'HTTP/1.1 200\r\n')
  331. self.assertEqual(protocol.response.version, (b'HTTP', 1, 1))
  332. self.assertEqual(protocol.response.code, 200)
  333. self.assertEqual(protocol.response.phrase, b'')
  334. def test_badResponseStatus(self):
  335. """
  336. L{HTTPClientParser.statusReceived} raises L{ParseError} if it is called
  337. with a status line which cannot be parsed.
  338. """
  339. protocol = HTTPClientParser(None, None)
  340. def checkParsing(s):
  341. exc = self.assertRaises(ParseError, protocol.statusReceived, s)
  342. self.assertEqual(exc.data, s)
  343. # If there are fewer than two whitespace-delimited parts to the status
  344. # line, it is not valid and cannot be parsed.
  345. checkParsing(b'foo')
  346. # If the response code is not an integer, the status line is not valid
  347. # and cannot be parsed.
  348. checkParsing(b'HTTP/1.1 bar OK')
  349. def _noBodyTest(self, request, status, response):
  350. """
  351. Assert that L{HTTPClientParser} parses the given C{response} to
  352. C{request}, resulting in a response with no body and no extra bytes and
  353. leaving the transport in the producing state.
  354. @param request: A L{Request} instance which might have caused a server
  355. to return the given response.
  356. @param status: A string giving the status line of the response to be
  357. parsed.
  358. @param response: A string giving the response to be parsed.
  359. @return: A C{dict} of headers from the response.
  360. """
  361. header = {}
  362. finished = []
  363. body = []
  364. bodyDataFinished = []
  365. protocol = HTTPClientParser(request, finished.append)
  366. protocol.headerReceived = header.__setitem__
  367. transport = StringTransport()
  368. protocol.makeConnection(transport)
  369. # Deliver just the status to initialize the response object so we can
  370. # monkey-patch it to observe progress of the response parser.
  371. protocol.dataReceived(status)
  372. protocol.response._bodyDataReceived = body.append
  373. protocol.response._bodyDataFinished = (
  374. lambda: bodyDataFinished.append(True))
  375. protocol.dataReceived(response)
  376. self.assertEqual(transport.producerState, u'producing')
  377. self.assertEqual(protocol.state, DONE)
  378. self.assertEqual(body, [])
  379. self.assertEqual(finished, [b''])
  380. self.assertEqual(bodyDataFinished, [True])
  381. self.assertEqual(protocol.response.length, 0)
  382. return header
  383. def test_headResponse(self):
  384. """
  385. If the response is to a HEAD request, no body is expected, the body
  386. callback is not invoked, and the I{Content-Length} header is passed to
  387. the header callback.
  388. """
  389. request = Request(b'HEAD', b'/', _boringHeaders, None)
  390. status = b'HTTP/1.1 200 OK\r\n'
  391. response = (
  392. b'Content-Length: 10\r\n'
  393. b'\r\n')
  394. header = self._noBodyTest(request, status, response)
  395. self.assertEqual(header, {b'Content-Length': b'10'})
  396. def test_noContentResponse(self):
  397. """
  398. If the response code is I{NO CONTENT} (204), no body is expected and
  399. the body callback is not invoked.
  400. """
  401. request = Request(b'GET', b'/', _boringHeaders, None)
  402. status = b'HTTP/1.1 204 NO CONTENT\r\n'
  403. response = b'\r\n'
  404. self._noBodyTest(request, status, response)
  405. def test_notModifiedResponse(self):
  406. """
  407. If the response code is I{NOT MODIFIED} (304), no body is expected and
  408. the body callback is not invoked.
  409. """
  410. request = Request(b'GET', b'/', _boringHeaders, None)
  411. status = b'HTTP/1.1 304 NOT MODIFIED\r\n'
  412. response = b'\r\n'
  413. self._noBodyTest(request, status, response)
  414. def test_responseHeaders(self):
  415. """
  416. The response headers are added to the response object's C{headers}
  417. L{Headers} instance.
  418. """
  419. protocol = HTTPClientParser(
  420. Request(b'GET', b'/', _boringHeaders, None),
  421. lambda rest: None)
  422. protocol.makeConnection(StringTransport())
  423. protocol.dataReceived(b'HTTP/1.1 200 OK\r\n')
  424. protocol.dataReceived(b'X-Foo: bar\r\n')
  425. protocol.dataReceived(b'\r\n')
  426. self.assertEqual(
  427. protocol.connHeaders,
  428. Headers({}))
  429. self.assertEqual(
  430. protocol.response.headers,
  431. Headers({b'x-foo': [b'bar']}))
  432. self.assertIdentical(protocol.response.length, UNKNOWN_LENGTH)
  433. def test_connectionHeaders(self):
  434. """
  435. The connection control headers are added to the parser's C{connHeaders}
  436. L{Headers} instance.
  437. """
  438. protocol = HTTPClientParser(
  439. Request(b'GET', b'/', _boringHeaders, None),
  440. lambda rest: None)
  441. protocol.makeConnection(StringTransport())
  442. protocol.dataReceived(b'HTTP/1.1 200 OK\r\n')
  443. protocol.dataReceived(b'Content-Length: 123\r\n')
  444. protocol.dataReceived(b'Connection: close\r\n')
  445. protocol.dataReceived(b'\r\n')
  446. self.assertEqual(
  447. protocol.response.headers,
  448. Headers({}))
  449. self.assertEqual(
  450. protocol.connHeaders,
  451. Headers({b'content-length': [b'123'],
  452. b'connection': [b'close']}))
  453. self.assertEqual(protocol.response.length, 123)
  454. def test_headResponseContentLengthEntityHeader(self):
  455. """
  456. If a HEAD request is made, the I{Content-Length} header in the response
  457. is added to the response headers, not the connection control headers.
  458. """
  459. protocol = HTTPClientParser(
  460. Request(b'HEAD', b'/', _boringHeaders, None),
  461. lambda rest: None)
  462. protocol.makeConnection(StringTransport())
  463. protocol.dataReceived(b'HTTP/1.1 200 OK\r\n')
  464. protocol.dataReceived(b'Content-Length: 123\r\n')
  465. protocol.dataReceived(b'\r\n')
  466. self.assertEqual(
  467. protocol.response.headers,
  468. Headers({b'content-length': [b'123']}))
  469. self.assertEqual(
  470. protocol.connHeaders,
  471. Headers({}))
  472. self.assertEqual(protocol.response.length, 0)
  473. def test_contentLength(self):
  474. """
  475. If a response includes a body with a length given by the
  476. I{Content-Length} header, the bytes which make up the body are passed
  477. to the C{_bodyDataReceived} callback on the L{HTTPParser}.
  478. """
  479. finished = []
  480. protocol = HTTPClientParser(
  481. Request(b'GET', b'/', _boringHeaders, None),
  482. finished.append)
  483. transport = StringTransport()
  484. protocol.makeConnection(transport)
  485. protocol.dataReceived(b'HTTP/1.1 200 OK\r\n')
  486. body = []
  487. protocol.response._bodyDataReceived = body.append
  488. protocol.dataReceived(b'Content-Length: 10\r\n')
  489. protocol.dataReceived(b'\r\n')
  490. # Incidentally, the transport should be paused now. It is the response
  491. # object's responsibility to resume this when it is ready for bytes.
  492. self.assertEqual(transport.producerState, u'paused')
  493. self.assertEqual(protocol.state, BODY)
  494. protocol.dataReceived(b'x' * 6)
  495. self.assertEqual(body, [b'x' * 6])
  496. self.assertEqual(protocol.state, BODY)
  497. protocol.dataReceived(b'y' * 4)
  498. self.assertEqual(body, [b'x' * 6, b'y' * 4])
  499. self.assertEqual(protocol.state, DONE)
  500. self.assertEqual(finished, [b''])
  501. def test_zeroContentLength(self):
  502. """
  503. If a response includes a I{Content-Length} header indicating zero bytes
  504. in the response, L{Response.length} is set accordingly and no data is
  505. delivered to L{Response._bodyDataReceived}.
  506. """
  507. finished = []
  508. protocol = HTTPClientParser(
  509. Request(b'GET', b'/', _boringHeaders, None),
  510. finished.append)
  511. protocol.makeConnection(StringTransport())
  512. protocol.dataReceived(b'HTTP/1.1 200 OK\r\n')
  513. body = []
  514. protocol.response._bodyDataReceived = body.append
  515. protocol.dataReceived(b'Content-Length: 0\r\n')
  516. protocol.dataReceived(b'\r\n')
  517. self.assertEqual(protocol.state, DONE)
  518. self.assertEqual(body, [])
  519. self.assertEqual(finished, [b''])
  520. self.assertEqual(protocol.response.length, 0)
  521. def test_multipleContentLengthHeaders(self):
  522. """
  523. If a response includes multiple I{Content-Length} headers,
  524. L{HTTPClientParser.dataReceived} raises L{ValueError} to indicate that
  525. the response is invalid and the transport is now unusable.
  526. """
  527. protocol = HTTPClientParser(
  528. Request(b'GET', b'/', _boringHeaders, None),
  529. None)
  530. protocol.makeConnection(StringTransport())
  531. self.assertRaises(
  532. ValueError,
  533. protocol.dataReceived,
  534. b'HTTP/1.1 200 OK\r\n'
  535. b'Content-Length: 1\r\n'
  536. b'Content-Length: 2\r\n'
  537. b'\r\n')
  538. def test_extraBytesPassedBack(self):
  539. """
  540. If extra bytes are received past the end of a response, they are passed
  541. to the finish callback.
  542. """
  543. finished = []
  544. protocol = HTTPClientParser(
  545. Request(b'GET', b'/', _boringHeaders, None),
  546. finished.append)
  547. protocol.makeConnection(StringTransport())
  548. protocol.dataReceived(b'HTTP/1.1 200 OK\r\n')
  549. protocol.dataReceived(b'Content-Length: 0\r\n')
  550. protocol.dataReceived(b'\r\nHere is another thing!')
  551. self.assertEqual(protocol.state, DONE)
  552. self.assertEqual(finished, [b'Here is another thing!'])
  553. def test_extraBytesPassedBackHEAD(self):
  554. """
  555. If extra bytes are received past the end of the headers of a response
  556. to a HEAD request, they are passed to the finish callback.
  557. """
  558. finished = []
  559. protocol = HTTPClientParser(
  560. Request(b'HEAD', b'/', _boringHeaders, None),
  561. finished.append)
  562. protocol.makeConnection(StringTransport())
  563. protocol.dataReceived(b'HTTP/1.1 200 OK\r\n')
  564. protocol.dataReceived(b'Content-Length: 12\r\n')
  565. protocol.dataReceived(b'\r\nHere is another thing!')
  566. self.assertEqual(protocol.state, DONE)
  567. self.assertEqual(finished, [b'Here is another thing!'])
  568. def test_chunkedResponseBody(self):
  569. """
  570. If the response headers indicate the response body is encoded with the
  571. I{chunked} transfer encoding, the body is decoded according to that
  572. transfer encoding before being passed to L{Response._bodyDataReceived}.
  573. """
  574. finished = []
  575. protocol = HTTPClientParser(
  576. Request(b'GET', b'/', _boringHeaders, None),
  577. finished.append)
  578. protocol.makeConnection(StringTransport())
  579. protocol.dataReceived(b'HTTP/1.1 200 OK\r\n')
  580. body = []
  581. protocol.response._bodyDataReceived = body.append
  582. protocol.dataReceived(b'Transfer-Encoding: chunked\r\n')
  583. protocol.dataReceived(b'\r\n')
  584. # No data delivered yet
  585. self.assertEqual(body, [])
  586. # Cannot predict the length of a chunked encoded response body.
  587. self.assertIdentical(protocol.response.length, UNKNOWN_LENGTH)
  588. # Deliver some chunks and make sure the data arrives
  589. protocol.dataReceived(b'3\r\na')
  590. self.assertEqual(body, [b'a'])
  591. protocol.dataReceived(b'bc\r\n')
  592. self.assertEqual(body, [b'a', b'bc'])
  593. # The response's _bodyDataFinished method should be called when the last
  594. # chunk is received. Extra data should be passed to the finished
  595. # callback.
  596. protocol.dataReceived(b'0\r\n\r\nextra')
  597. self.assertEqual(finished, [b'extra'])
  598. def test_unknownContentLength(self):
  599. """
  600. If a response does not include a I{Transfer-Encoding} or a
  601. I{Content-Length}, the end of response body is indicated by the
  602. connection being closed.
  603. """
  604. finished = []
  605. protocol = HTTPClientParser(
  606. Request(b'GET', b'/', _boringHeaders, None), finished.append)
  607. transport = StringTransport()
  608. protocol.makeConnection(transport)
  609. protocol.dataReceived(b'HTTP/1.1 200 OK\r\n')
  610. body = []
  611. protocol.response._bodyDataReceived = body.append
  612. protocol.dataReceived(b'\r\n')
  613. protocol.dataReceived(b'foo')
  614. protocol.dataReceived(b'bar')
  615. self.assertEqual(body, [b'foo', b'bar'])
  616. protocol.connectionLost(ConnectionDone(u"simulated end of connection"))
  617. self.assertEqual(finished, [b''])
  618. def test_contentLengthAndTransferEncoding(self):
  619. """
  620. According to RFC 2616, section 4.4, point 3, if I{Content-Length} and
  621. I{Transfer-Encoding: chunked} are present, I{Content-Length} MUST be
  622. ignored
  623. """
  624. finished = []
  625. protocol = HTTPClientParser(
  626. Request(b'GET', b'/', _boringHeaders, None), finished.append)
  627. transport = StringTransport()
  628. protocol.makeConnection(transport)
  629. protocol.dataReceived(b'HTTP/1.1 200 OK\r\n')
  630. body = []
  631. protocol.response._bodyDataReceived = body.append
  632. protocol.dataReceived(
  633. b'Content-Length: 102\r\n'
  634. b'Transfer-Encoding: chunked\r\n'
  635. b'\r\n'
  636. b'3\r\n'
  637. b'abc\r\n'
  638. b'0\r\n'
  639. b'\r\n')
  640. self.assertEqual(body, [b'abc'])
  641. self.assertEqual(finished, [b''])
  642. def test_connectionLostBeforeBody(self):
  643. """
  644. If L{HTTPClientParser.connectionLost} is called before the headers are
  645. finished, the C{_responseDeferred} is fired with the L{Failure} passed
  646. to C{connectionLost}.
  647. """
  648. transport = StringTransport()
  649. protocol = HTTPClientParser(Request(b'GET', b'/', _boringHeaders,
  650. None), None)
  651. protocol.makeConnection(transport)
  652. # Grab this here because connectionLost gets rid of the attribute
  653. responseDeferred = protocol._responseDeferred
  654. protocol.connectionLost(Failure(ArbitraryException()))
  655. return assertResponseFailed(
  656. self, responseDeferred, [ArbitraryException])
  657. def test_connectionLostWithError(self):
  658. """
  659. If one of the L{Response} methods called by
  660. L{HTTPClientParser.connectionLost} raises an exception, the exception
  661. is logged and not re-raised.
  662. """
  663. transport = StringTransport()
  664. protocol = HTTPClientParser(Request(b'GET', b'/', _boringHeaders, None),
  665. None)
  666. protocol.makeConnection(transport)
  667. response = []
  668. protocol._responseDeferred.addCallback(response.append)
  669. protocol.dataReceived(
  670. b'HTTP/1.1 200 OK\r\n'
  671. b'Content-Length: 1\r\n'
  672. b'\r\n')
  673. response = response[0]
  674. # Arrange for an exception
  675. def fakeBodyDataFinished(err=None):
  676. raise ArbitraryException()
  677. response._bodyDataFinished = fakeBodyDataFinished
  678. protocol.connectionLost(None)
  679. self.assertEqual(len(self.flushLoggedErrors(ArbitraryException)), 1)
  680. def test_noResponseAtAll(self):
  681. """
  682. If no response at all was received and the connection is lost, the
  683. resulting error is L{ResponseNeverReceived}.
  684. """
  685. protocol = HTTPClientParser(
  686. Request(b'HEAD', b'/', _boringHeaders, None),
  687. lambda ign: None)
  688. d = protocol._responseDeferred
  689. protocol.makeConnection(StringTransport())
  690. protocol.connectionLost(ConnectionLost())
  691. return self.assertFailure(d, ResponseNeverReceived)
  692. def test_someResponseButNotAll(self):
  693. """
  694. If a partial response was received and the connection is lost, the
  695. resulting error is L{ResponseFailed}, but not
  696. L{ResponseNeverReceived}.
  697. """
  698. protocol = HTTPClientParser(
  699. Request(b'HEAD', b'/', _boringHeaders, None),
  700. lambda ign: None)
  701. d = protocol._responseDeferred
  702. protocol.makeConnection(StringTransport())
  703. protocol.dataReceived(b'2')
  704. protocol.connectionLost(ConnectionLost())
  705. return self.assertFailure(d, ResponseFailed).addCallback(
  706. self.assertIsInstance, ResponseFailed)
  707. def test_1XXResponseIsSwallowed(self):
  708. """
  709. If a response in the 1XX range is received it just gets swallowed and
  710. the parser resets itself.
  711. """
  712. sample103Response = (
  713. b'HTTP/1.1 103 Early Hints\r\n'
  714. b'Server: socketserver/1.0.0\r\n'
  715. b'Link: </other/styles.css>; rel=preload; as=style\r\n'
  716. b'Link: </other/action.js>; rel=preload; as=script\r\n'
  717. b'\r\n'
  718. )
  719. protocol = HTTPClientParser(
  720. Request(b'GET', b'/', _boringHeaders, None),
  721. lambda ign: None
  722. )
  723. protocol.makeConnection(StringTransport())
  724. protocol.dataReceived(sample103Response)
  725. # The response should have been erased
  726. self.assertTrue(getattr(protocol, 'response', None) is None)
  727. self.assertEqual(protocol.state, STATUS)
  728. self.assertEqual(len(list(protocol.headers.getAllRawHeaders())), 0)
  729. self.assertEqual(len(list(protocol.connHeaders.getAllRawHeaders())), 0)
  730. self.assertTrue(protocol._everReceivedData)
  731. def test_1XXFollowedByFinalResponseOnlyEmitsFinal(self):
  732. """
  733. When a 1XX response is swallowed, the final response that follows it is
  734. the only one that gets sent to the application.
  735. """
  736. sample103Response = (
  737. b'HTTP/1.1 103 Early Hints\r\n'
  738. b'Server: socketserver/1.0.0\r\n'
  739. b'Link: </other/styles.css>; rel=preload; as=style\r\n'
  740. b'Link: </other/action.js>; rel=preload; as=script\r\n'
  741. b'\r\n'
  742. )
  743. following200Response = (
  744. b'HTTP/1.1 200 OK\r\n'
  745. b'Content-Length: 123\r\n'
  746. b'\r\n'
  747. )
  748. protocol = HTTPClientParser(
  749. Request(b'GET', b'/', _boringHeaders, None),
  750. lambda ign: None
  751. )
  752. protocol.makeConnection(StringTransport())
  753. protocol.dataReceived(sample103Response + following200Response)
  754. self.assertEqual(protocol.response.code, 200)
  755. self.assertEqual(
  756. protocol.response.headers,
  757. Headers({}))
  758. self.assertEqual(
  759. protocol.connHeaders,
  760. Headers({b'content-length': [b'123']}))
  761. self.assertEqual(protocol.response.length, 123)
  762. def test_multiple1XXResponsesAreIgnored(self):
  763. """
  764. It is acceptable for multiple 1XX responses to come through, all of
  765. which get ignored.
  766. """
  767. sample103Response = (
  768. b'HTTP/1.1 103 Early Hints\r\n'
  769. b'Server: socketserver/1.0.0\r\n'
  770. b'Link: </other/styles.css>; rel=preload; as=style\r\n'
  771. b'Link: </other/action.js>; rel=preload; as=script\r\n'
  772. b'\r\n'
  773. )
  774. following200Response = (
  775. b'HTTP/1.1 200 OK\r\n'
  776. b'Content-Length: 123\r\n'
  777. b'\r\n'
  778. )
  779. protocol = HTTPClientParser(
  780. Request(b'GET', b'/', _boringHeaders, None),
  781. lambda ign: None
  782. )
  783. protocol.makeConnection(StringTransport())
  784. protocol.dataReceived(
  785. sample103Response +
  786. sample103Response +
  787. sample103Response +
  788. following200Response
  789. )
  790. self.assertEqual(protocol.response.code, 200)
  791. self.assertEqual(
  792. protocol.response.headers,
  793. Headers({}))
  794. self.assertEqual(
  795. protocol.connHeaders,
  796. Headers({b'content-length': [b'123']}))
  797. self.assertEqual(protocol.response.length, 123)
  798. def test_ignored1XXResponseCausesLog(self):
  799. """
  800. When a 1XX response is ignored, Twisted emits a log.
  801. """
  802. sample103Response = (
  803. b'HTTP/1.1 103 Early Hints\r\n'
  804. b'Server: socketserver/1.0.0\r\n'
  805. b'Link: </other/styles.css>; rel=preload; as=style\r\n'
  806. b'Link: </other/action.js>; rel=preload; as=script\r\n'
  807. b'\r\n'
  808. )
  809. # Catch the logs.
  810. logs = []
  811. log.addObserver(logs.append)
  812. self.addCleanup(log.removeObserver, logs.append)
  813. protocol = HTTPClientParser(
  814. Request(b'GET', b'/', _boringHeaders, None),
  815. lambda ign: None
  816. )
  817. protocol.makeConnection(StringTransport())
  818. protocol.dataReceived(sample103Response)
  819. self.assertEqual(
  820. logs[0]['message'][0], 'Ignoring unexpected 103 response'
  821. )
  822. class SlowRequest:
  823. """
  824. L{SlowRequest} is a fake implementation of L{Request} which is easily
  825. controlled externally (for example, by code in a test method).
  826. @ivar stopped: A flag indicating whether C{stopWriting} has been called.
  827. @ivar finished: After C{writeTo} is called, a L{Deferred} which was
  828. returned by that method. L{SlowRequest} will never fire this
  829. L{Deferred}.
  830. """
  831. method = b'GET'
  832. stopped = False
  833. persistent = False
  834. def writeTo(self, transport):
  835. self.finished = Deferred()
  836. return self.finished
  837. def stopWriting(self):
  838. self.stopped = True
  839. class SimpleRequest:
  840. """
  841. L{SimpleRequest} is a fake implementation of L{Request} which writes a
  842. short, fixed string to the transport passed to its C{writeTo} method and
  843. returns a succeeded L{Deferred}. This vaguely emulates the behavior of a
  844. L{Request} with no body producer.
  845. """
  846. persistent = False
  847. def writeTo(self, transport):
  848. transport.write(b'SOME BYTES')
  849. return succeed(None)
  850. class HTTP11ClientProtocolTests(TestCase):
  851. """
  852. Tests for the HTTP 1.1 client protocol implementation,
  853. L{HTTP11ClientProtocol}.
  854. """
  855. def setUp(self):
  856. """
  857. Create an L{HTTP11ClientProtocol} connected to a fake transport.
  858. """
  859. self.transport = StringTransport()
  860. self.protocol = HTTP11ClientProtocol()
  861. self.protocol.makeConnection(self.transport)
  862. def test_request(self):
  863. """
  864. L{HTTP11ClientProtocol.request} accepts a L{Request} and calls its
  865. C{writeTo} method with its own transport.
  866. """
  867. self.protocol.request(SimpleRequest())
  868. self.assertEqual(self.transport.value(), b'SOME BYTES')
  869. def test_secondRequest(self):
  870. """
  871. The second time L{HTTP11ClientProtocol.request} is called, it returns a
  872. L{Deferred} which immediately fires with a L{Failure} wrapping a
  873. L{RequestNotSent} exception.
  874. """
  875. self.protocol.request(SlowRequest())
  876. def cbNotSent(ignored):
  877. self.assertEqual(self.transport.value(), b'')
  878. d = self.assertFailure(
  879. self.protocol.request(SimpleRequest()), RequestNotSent)
  880. d.addCallback(cbNotSent)
  881. return d
  882. def test_requestAfterConnectionLost(self):
  883. """
  884. L{HTTP11ClientProtocol.request} returns a L{Deferred} which immediately
  885. fires with a L{Failure} wrapping a L{RequestNotSent} if called after
  886. the protocol has been disconnected.
  887. """
  888. self.protocol.connectionLost(
  889. Failure(ConnectionDone(u"sad transport")))
  890. def cbNotSent(ignored):
  891. self.assertEqual(self.transport.value(), b'')
  892. d = self.assertFailure(
  893. self.protocol.request(SimpleRequest()), RequestNotSent)
  894. d.addCallback(cbNotSent)
  895. return d
  896. def test_failedWriteTo(self):
  897. """
  898. If the L{Deferred} returned by L{Request.writeTo} fires with a
  899. L{Failure}, L{HTTP11ClientProtocol.request} disconnects its transport
  900. and returns a L{Deferred} which fires with a L{Failure} of
  901. L{RequestGenerationFailed} wrapping the underlying failure.
  902. """
  903. class BrokenRequest:
  904. persistent = False
  905. def writeTo(self, transport):
  906. return fail(ArbitraryException())
  907. d = self.protocol.request(BrokenRequest())
  908. def cbFailed(ignored):
  909. self.assertTrue(self.transport.disconnecting)
  910. # Simulate what would happen if the protocol had a real transport
  911. # and make sure no exception is raised.
  912. self.protocol.connectionLost(
  913. Failure(ConnectionDone(u"you asked for it")))
  914. d = assertRequestGenerationFailed(self, d, [ArbitraryException])
  915. d.addCallback(cbFailed)
  916. return d
  917. def test_synchronousWriteToError(self):
  918. """
  919. If L{Request.writeTo} raises an exception,
  920. L{HTTP11ClientProtocol.request} returns a L{Deferred} which fires with
  921. a L{Failure} of L{RequestGenerationFailed} wrapping that exception.
  922. """
  923. class BrokenRequest:
  924. persistent = False
  925. def writeTo(self, transport):
  926. raise ArbitraryException()
  927. d = self.protocol.request(BrokenRequest())
  928. return assertRequestGenerationFailed(self, d, [ArbitraryException])
  929. def test_connectionLostDuringRequestGeneration(self, mode=None):
  930. """
  931. If L{HTTP11ClientProtocol}'s transport is disconnected before the
  932. L{Deferred} returned by L{Request.writeTo} fires, the L{Deferred}
  933. returned by L{HTTP11ClientProtocol.request} fires with a L{Failure} of
  934. L{RequestTransmissionFailed} wrapping the underlying failure.
  935. """
  936. request = SlowRequest()
  937. d = self.protocol.request(request)
  938. d = assertRequestTransmissionFailed(self, d, [ArbitraryException])
  939. # The connection hasn't been lost yet. The request should still be
  940. # allowed to do its thing.
  941. self.assertFalse(request.stopped)
  942. self.protocol.connectionLost(Failure(ArbitraryException()))
  943. # Now the connection has been lost. The request should have been told
  944. # to stop writing itself.
  945. self.assertTrue(request.stopped)
  946. if mode == 'callback':
  947. request.finished.callback(None)
  948. elif mode == 'errback':
  949. request.finished.errback(Failure(AnotherArbitraryException()))
  950. errors = self.flushLoggedErrors(AnotherArbitraryException)
  951. self.assertEqual(len(errors), 1)
  952. else:
  953. # Don't fire the writeTo Deferred at all.
  954. pass
  955. return d
  956. def test_connectionLostBeforeGenerationFinished(self):
  957. """
  958. If the request passed to L{HTTP11ClientProtocol} finishes generation
  959. successfully after the L{HTTP11ClientProtocol}'s connection has been
  960. lost, nothing happens.
  961. """
  962. return self.test_connectionLostDuringRequestGeneration('callback')
  963. def test_connectionLostBeforeGenerationFailed(self):
  964. """
  965. If the request passed to L{HTTP11ClientProtocol} finished generation
  966. with an error after the L{HTTP11ClientProtocol}'s connection has been
  967. lost, nothing happens.
  968. """
  969. return self.test_connectionLostDuringRequestGeneration('errback')
  970. def test_errorMessageOnConnectionLostBeforeGenerationFailedDoesNotConfuse(self):
  971. """
  972. If the request passed to L{HTTP11ClientProtocol} finished generation
  973. with an error after the L{HTTP11ClientProtocol}'s connection has been
  974. lost, an error is logged that gives a non-confusing hint to user on what
  975. went wrong.
  976. """
  977. errors = []
  978. log.addObserver(errors.append)
  979. self.addCleanup(log.removeObserver, errors.append)
  980. def check(ignore):
  981. error = errors[0]
  982. self.assertEqual(error[u'why'],
  983. u'Error writing request, but not in valid state '
  984. u'to finalize request: CONNECTION_LOST')
  985. return self.test_connectionLostDuringRequestGeneration(
  986. 'errback').addCallback(check)
  987. def test_receiveSimplestResponse(self):
  988. """
  989. When a response is delivered to L{HTTP11ClientProtocol}, the
  990. L{Deferred} previously returned by the C{request} method is called back
  991. with a L{Response} instance and the connection is closed.
  992. """
  993. d = self.protocol.request(Request(b'GET', b'/', _boringHeaders, None))
  994. def cbRequest(response):
  995. self.assertEqual(response.code, 200)
  996. self.assertEqual(response.headers, Headers())
  997. self.assertTrue(self.transport.disconnecting)
  998. self.assertEqual(self.protocol.state, u'QUIESCENT')
  999. d.addCallback(cbRequest)
  1000. self.protocol.dataReceived(
  1001. b"HTTP/1.1 200 OK\r\n"
  1002. b"Content-Length: 0\r\n"
  1003. b"Connection: close\r\n"
  1004. b"\r\n")
  1005. return d
  1006. def test_receiveResponseHeaders(self):
  1007. """
  1008. The headers included in a response delivered to L{HTTP11ClientProtocol}
  1009. are included on the L{Response} instance passed to the callback
  1010. returned by the C{request} method.
  1011. """
  1012. d = self.protocol.request(Request(b'GET', b'/', _boringHeaders, None))
  1013. def cbRequest(response):
  1014. expected = Headers({b'x-foo': [b'bar', b'baz']})
  1015. self.assertEqual(response.headers, expected)
  1016. d.addCallback(cbRequest)
  1017. self.protocol.dataReceived(
  1018. b"HTTP/1.1 200 OK\r\n"
  1019. b"X-Foo: bar\r\n"
  1020. b"X-Foo: baz\r\n"
  1021. b"\r\n")
  1022. return d
  1023. def test_receiveResponseBeforeRequestGenerationDone(self):
  1024. """
  1025. If response bytes are delivered to L{HTTP11ClientProtocol} before the
  1026. L{Deferred} returned by L{Request.writeTo} fires, those response bytes
  1027. are parsed as part of the response.
  1028. The connection is also closed, because we're in a confusing state, and
  1029. therefore the C{quiescentCallback} isn't called.
  1030. """
  1031. quiescentResult = []
  1032. transport = StringTransport()
  1033. protocol = HTTP11ClientProtocol(quiescentResult.append)
  1034. protocol.makeConnection(transport)
  1035. request = SlowRequest()
  1036. d = protocol.request(request)
  1037. protocol.dataReceived(
  1038. b"HTTP/1.1 200 OK\r\n"
  1039. b"X-Foo: bar\r\n"
  1040. b"Content-Length: 6\r\n"
  1041. b"\r\n"
  1042. b"foobar")
  1043. def cbResponse(response):
  1044. p = AccumulatingProtocol()
  1045. whenFinished = p.closedDeferred = Deferred()
  1046. response.deliverBody(p)
  1047. self.assertEqual(
  1048. protocol.state, u'TRANSMITTING_AFTER_RECEIVING_RESPONSE')
  1049. self.assertTrue(transport.disconnecting)
  1050. self.assertEqual(quiescentResult, [])
  1051. return whenFinished.addCallback(
  1052. lambda ign: (response, p.data))
  1053. d.addCallback(cbResponse)
  1054. def cbAllResponse(result):
  1055. response, body = result
  1056. self.assertEqual(response.version, (b'HTTP', 1, 1))
  1057. self.assertEqual(response.code, 200)
  1058. self.assertEqual(response.phrase, b'OK')
  1059. self.assertEqual(response.headers, Headers({b'x-foo': [b'bar']}))
  1060. self.assertEqual(body, b"foobar")
  1061. # Also nothing bad should happen if the request does finally
  1062. # finish, even though it is completely irrelevant.
  1063. request.finished.callback(None)
  1064. d.addCallback(cbAllResponse)
  1065. return d
  1066. def test_connectionLostAfterReceivingResponseBeforeRequestGenerationDone(self):
  1067. """
  1068. If response bytes are delivered to L{HTTP11ClientProtocol} before the
  1069. request completes, calling C{connectionLost} on the protocol will
  1070. result in protocol being moved to C{'CONNECTION_LOST'} state.
  1071. """
  1072. request = SlowRequest()
  1073. d = self.protocol.request(request)
  1074. self.protocol.dataReceived(
  1075. b"HTTP/1.1 400 BAD REQUEST\r\n"
  1076. b"Content-Length: 9\r\n"
  1077. b"\r\n"
  1078. b"tisk tisk")
  1079. def cbResponse(response):
  1080. p = AccumulatingProtocol()
  1081. whenFinished = p.closedDeferred = Deferred()
  1082. response.deliverBody(p)
  1083. return whenFinished.addCallback(
  1084. lambda ign: (response, p.data))
  1085. d.addCallback(cbResponse)
  1086. def cbAllResponse(ignore):
  1087. request.finished.callback(None)
  1088. # Nothing dire will happen when the connection is lost
  1089. self.protocol.connectionLost(Failure(ArbitraryException()))
  1090. self.assertEqual(self.protocol._state, u'CONNECTION_LOST')
  1091. d.addCallback(cbAllResponse)
  1092. return d
  1093. def test_receiveResponseBody(self):
  1094. """
  1095. The C{deliverBody} method of the response object with which the
  1096. L{Deferred} returned by L{HTTP11ClientProtocol.request} fires can be
  1097. used to get the body of the response.
  1098. """
  1099. protocol = AccumulatingProtocol()
  1100. whenFinished = protocol.closedDeferred = Deferred()
  1101. requestDeferred = self.protocol.request(Request(b'GET', b'/', _boringHeaders, None))
  1102. self.protocol.dataReceived(
  1103. b"HTTP/1.1 200 OK\r\n"
  1104. b"Content-Length: 6\r\n"
  1105. b"\r")
  1106. # Here's what's going on: all the response headers have been delivered
  1107. # by this point, so the request Deferred can fire with a Response
  1108. # object. The body is yet to come, but that's okay, because the
  1109. # Response object is how you *get* the body.
  1110. result = []
  1111. requestDeferred.addCallback(result.append)
  1112. self.assertEqual(result, [])
  1113. # Deliver the very last byte of the response. It is exactly at this
  1114. # point which the Deferred returned by request should fire.
  1115. self.protocol.dataReceived(b"\n")
  1116. response = result[0]
  1117. response.deliverBody(protocol)
  1118. self.protocol.dataReceived(b"foo")
  1119. self.protocol.dataReceived(b"bar")
  1120. def cbAllResponse(ignored):
  1121. self.assertEqual(protocol.data, b"foobar")
  1122. protocol.closedReason.trap(ResponseDone)
  1123. whenFinished.addCallback(cbAllResponse)
  1124. return whenFinished
  1125. def test_responseBodyFinishedWhenConnectionLostWhenContentLengthIsUnknown(
  1126. self):
  1127. """
  1128. If the length of the response body is unknown, the protocol passed to
  1129. the response's C{deliverBody} method has its C{connectionLost}
  1130. method called with a L{Failure} wrapping a L{PotentialDataLoss}
  1131. exception.
  1132. """
  1133. requestDeferred = self.protocol.request(Request(b'GET', b'/',
  1134. _boringHeaders, None))
  1135. self.protocol.dataReceived(
  1136. b"HTTP/1.1 200 OK\r\n"
  1137. b"\r\n")
  1138. result = []
  1139. requestDeferred.addCallback(result.append)
  1140. response = result[0]
  1141. protocol = AccumulatingProtocol()
  1142. response.deliverBody(protocol)
  1143. self.protocol.dataReceived(b"foo")
  1144. self.protocol.dataReceived(b"bar")
  1145. self.assertEqual(protocol.data, b"foobar")
  1146. self.protocol.connectionLost(
  1147. Failure(ConnectionDone(u"low-level transport disconnected")))
  1148. protocol.closedReason.trap(PotentialDataLoss)
  1149. def test_chunkedResponseBodyUnfinishedWhenConnectionLost(self):
  1150. """
  1151. If the final chunk has not been received when the connection is lost
  1152. (for any reason), the protocol passed to C{deliverBody} has its
  1153. C{connectionLost} method called with a L{Failure} wrapping the
  1154. exception for that reason.
  1155. """
  1156. requestDeferred = self.protocol.request(Request(b'GET', b'/',
  1157. _boringHeaders, None))
  1158. self.protocol.dataReceived(
  1159. b"HTTP/1.1 200 OK\r\n"
  1160. b"Transfer-Encoding: chunked\r\n"
  1161. b"\r\n")
  1162. result = []
  1163. requestDeferred.addCallback(result.append)
  1164. response = result[0]
  1165. protocol = AccumulatingProtocol()
  1166. response.deliverBody(protocol)
  1167. self.protocol.dataReceived(b"3\r\nfoo\r\n")
  1168. self.protocol.dataReceived(b"3\r\nbar\r\n")
  1169. self.assertEqual(protocol.data, b"foobar")
  1170. self.protocol.connectionLost(Failure(ArbitraryException()))
  1171. return assertResponseFailed(
  1172. self, fail(protocol.closedReason), [ArbitraryException, _DataLoss])
  1173. def test_parserDataReceivedException(self):
  1174. """
  1175. If the parser L{HTTP11ClientProtocol} delivers bytes to in
  1176. C{dataReceived} raises an exception, the exception is wrapped in a
  1177. L{Failure} and passed to the parser's C{connectionLost} and then the
  1178. L{HTTP11ClientProtocol}'s transport is disconnected.
  1179. """
  1180. requestDeferred = self.protocol.request(Request(b'GET', b'/',
  1181. _boringHeaders, None))
  1182. self.protocol.dataReceived(b'unparseable garbage goes here\r\n')
  1183. d = assertResponseFailed(self, requestDeferred, [ParseError])
  1184. def cbFailed(exc):
  1185. self.assertTrue(self.transport.disconnecting)
  1186. self.assertEqual(
  1187. exc.reasons[0].value.data, b'unparseable garbage goes here')
  1188. # Now do what StringTransport doesn't do but a real transport would
  1189. # have, call connectionLost on the HTTP11ClientProtocol. Nothing
  1190. # is asserted about this, but it's important for it to not raise an
  1191. # exception.
  1192. self.protocol.connectionLost(Failure(ConnectionDone(u"it is done")))
  1193. d.addCallback(cbFailed)
  1194. return d
  1195. def test_proxyStopped(self):
  1196. """
  1197. When the HTTP response parser is disconnected, the
  1198. L{TransportProxyProducer} which was connected to it as a transport is
  1199. stopped.
  1200. """
  1201. requestDeferred = self.protocol.request(Request(b'GET', b'/',
  1202. _boringHeaders, None))
  1203. transport = self.protocol._parser.transport
  1204. self.assertIdentical(transport._producer, self.transport)
  1205. self.protocol._disconnectParser(
  1206. Failure(ConnectionDone(u"connection done")))
  1207. self.assertIdentical(transport._producer, None)
  1208. return assertResponseFailed(self, requestDeferred, [ConnectionDone])
  1209. def test_abortClosesConnection(self):
  1210. """
  1211. L{HTTP11ClientProtocol.abort} will tell the transport to close its
  1212. connection when it is invoked, and returns a C{Deferred} that fires
  1213. when the connection is lost.
  1214. """
  1215. transport = StringTransport()
  1216. protocol = HTTP11ClientProtocol()
  1217. protocol.makeConnection(transport)
  1218. r1 = []
  1219. r2 = []
  1220. protocol.abort().addCallback(r1.append)
  1221. protocol.abort().addCallback(r2.append)
  1222. self.assertEqual((r1, r2), ([], []))
  1223. self.assertTrue(transport.disconnecting)
  1224. # Disconnect protocol, the Deferreds will fire:
  1225. protocol.connectionLost(Failure(ConnectionDone()))
  1226. self.assertEqual(r1, [None])
  1227. self.assertEqual(r2, [None])
  1228. def test_abortAfterConnectionLost(self):
  1229. """
  1230. L{HTTP11ClientProtocol.abort} called after the connection is lost
  1231. returns a C{Deferred} that fires immediately.
  1232. """
  1233. transport = StringTransport()
  1234. protocol = HTTP11ClientProtocol()
  1235. protocol.makeConnection(transport)
  1236. protocol.connectionLost(Failure(ConnectionDone()))
  1237. result = []
  1238. protocol.abort().addCallback(result.append)
  1239. self.assertEqual(result, [None])
  1240. self.assertEqual(protocol._state, u"CONNECTION_LOST")
  1241. def test_abortBeforeResponseBody(self):
  1242. """
  1243. The Deferred returned by L{HTTP11ClientProtocol.request} will fire
  1244. with a L{ResponseFailed} failure containing a L{ConnectionAborted}
  1245. exception, if the connection was aborted before all response headers
  1246. have been received.
  1247. """
  1248. transport = StringTransport()
  1249. protocol = HTTP11ClientProtocol()
  1250. protocol.makeConnection(transport)
  1251. result = protocol.request(Request(b'GET', b'/', _boringHeaders, None))
  1252. protocol.abort()
  1253. self.assertTrue(transport.disconnecting)
  1254. protocol.connectionLost(Failure(ConnectionDone()))
  1255. return assertResponseFailed(self, result, [ConnectionAborted])
  1256. def test_abortAfterResponseHeaders(self):
  1257. """
  1258. When the connection is aborted after the response headers have
  1259. been received and the L{Response} has been made available to
  1260. application code, the response body protocol's C{connectionLost}
  1261. method will be invoked with a L{ResponseFailed} failure containing a
  1262. L{ConnectionAborted} exception.
  1263. """
  1264. # We need to set StringTransport to lenient mode because we'll call
  1265. # resumeProducing on it after the connection is aborted. That's ok:
  1266. # for real transports nothing will happen.
  1267. transport = StringTransport(lenient=True)
  1268. protocol = HTTP11ClientProtocol()
  1269. protocol.makeConnection(transport)
  1270. result = protocol.request(Request(b'GET', b'/', _boringHeaders, None))
  1271. protocol.dataReceived(
  1272. b"HTTP/1.1 200 OK\r\n"
  1273. b"Content-Length: 1\r\n"
  1274. b"\r\n"
  1275. )
  1276. testResult = Deferred()
  1277. class BodyDestination(Protocol):
  1278. """
  1279. A body response protocol which immediately aborts the HTTP
  1280. connection.
  1281. """
  1282. def connectionMade(self):
  1283. """
  1284. Abort the HTTP connection.
  1285. """
  1286. protocol.abort()
  1287. def connectionLost(self, reason):
  1288. """
  1289. Make the reason for the losing of the connection available to
  1290. the unit test via C{testResult}.
  1291. """
  1292. testResult.errback(reason)
  1293. def deliverBody(response):
  1294. """
  1295. Connect the L{BodyDestination} response body protocol to the
  1296. response, and then simulate connection loss after ensuring that
  1297. the HTTP connection has been aborted.
  1298. """
  1299. response.deliverBody(BodyDestination())
  1300. self.assertTrue(transport.disconnecting)
  1301. protocol.connectionLost(Failure(ConnectionDone()))
  1302. def checkError(error):
  1303. self.assertIsInstance(error.response, Response)
  1304. result.addCallback(deliverBody)
  1305. deferred = assertResponseFailed(self, testResult,
  1306. [ConnectionAborted, _DataLoss])
  1307. return deferred.addCallback(checkError)
  1308. def test_quiescentCallbackCalled(self):
  1309. """
  1310. If after a response is done the {HTTP11ClientProtocol} stays open and
  1311. returns to QUIESCENT state, all per-request state is reset and the
  1312. C{quiescentCallback} is called with the protocol instance.
  1313. This is useful for implementing a persistent connection pool.
  1314. The C{quiescentCallback} is called *before* the response-receiving
  1315. protocol's C{connectionLost}, so that new requests triggered by end of
  1316. first request can re-use a persistent connection.
  1317. """
  1318. quiescentResult = []
  1319. def callback(p):
  1320. self.assertEqual(p, protocol)
  1321. self.assertEqual(p.state, u"QUIESCENT")
  1322. quiescentResult.append(p)
  1323. transport = StringTransport()
  1324. protocol = HTTP11ClientProtocol(callback)
  1325. protocol.makeConnection(transport)
  1326. requestDeferred = protocol.request(
  1327. Request(b'GET', b'/', _boringHeaders, None, persistent=True))
  1328. protocol.dataReceived(
  1329. b"HTTP/1.1 200 OK\r\n"
  1330. b"Content-length: 3\r\n"
  1331. b"\r\n")
  1332. # Headers done, but still no quiescent callback:
  1333. self.assertEqual(quiescentResult, [])
  1334. result = []
  1335. requestDeferred.addCallback(result.append)
  1336. response = result[0]
  1337. # When response body is done (i.e. connectionLost is called), note the
  1338. # fact in quiescentResult:
  1339. bodyProtocol = AccumulatingProtocol()
  1340. bodyProtocol.closedDeferred = Deferred()
  1341. bodyProtocol.closedDeferred.addCallback(
  1342. lambda ign: quiescentResult.append(u"response done"))
  1343. response.deliverBody(bodyProtocol)
  1344. protocol.dataReceived(b"abc")
  1345. bodyProtocol.closedReason.trap(ResponseDone)
  1346. # Quiescent callback called *before* protocol handling the response
  1347. # body gets its connectionLost called:
  1348. self.assertEqual(quiescentResult, [protocol, u"response done"])
  1349. # Make sure everything was cleaned up:
  1350. self.assertEqual(protocol._parser, None)
  1351. self.assertEqual(protocol._finishedRequest, None)
  1352. self.assertEqual(protocol._currentRequest, None)
  1353. self.assertEqual(protocol._transportProxy, None)
  1354. self.assertEqual(protocol._responseDeferred, None)
  1355. def test_transportProducingWhenQuiescentAfterFullBody(self):
  1356. """
  1357. The C{quiescentCallback} passed to L{HTTP11ClientProtocol} will only be
  1358. invoked once that protocol is in a state similar to its initial state.
  1359. One of the aspects of this initial state is the producer-state of its
  1360. transport; an L{HTTP11ClientProtocol} begins with a transport that is
  1361. producing, i.e. not C{pauseProducing}'d.
  1362. Therefore, when C{quiescentCallback} is invoked the protocol will still
  1363. be producing.
  1364. """
  1365. quiescentResult = []
  1366. def callback(p):
  1367. self.assertEqual(p, protocol)
  1368. self.assertEqual(p.state, u"QUIESCENT")
  1369. quiescentResult.append(p)
  1370. transport = StringTransport()
  1371. protocol = HTTP11ClientProtocol(callback)
  1372. protocol.makeConnection(transport)
  1373. requestDeferred = protocol.request(
  1374. Request(b'GET', b'/', _boringHeaders, None, persistent=True))
  1375. protocol.dataReceived(
  1376. b"HTTP/1.1 200 OK\r\n"
  1377. b"Content-length: 3\r\n"
  1378. b"\r\n"
  1379. b"BBB" # _full_ content of the response.
  1380. )
  1381. response = self.successResultOf(requestDeferred)
  1382. # Sanity check: response should have full response body, just waiting
  1383. # for deliverBody
  1384. self.assertEqual(response._state, u'DEFERRED_CLOSE')
  1385. # The transport is quiescent, because the response has been received.
  1386. # If we were connection pooling here, it would have been returned to
  1387. # the pool.
  1388. self.assertEqual(len(quiescentResult), 1)
  1389. # And that transport is totally still reading, right? Because it would
  1390. # leak forever if it were sitting there disconnected from the
  1391. # reactor...
  1392. self.assertEqual(transport.producerState, u'producing')
  1393. def test_quiescentCallbackCalledEmptyResponse(self):
  1394. """
  1395. The quiescentCallback is called before the request C{Deferred} fires,
  1396. in cases where the response has no body.
  1397. """
  1398. quiescentResult = []
  1399. def callback(p):
  1400. self.assertEqual(p, protocol)
  1401. self.assertEqual(p.state, u"QUIESCENT")
  1402. quiescentResult.append(p)
  1403. transport = StringTransport()
  1404. protocol = HTTP11ClientProtocol(callback)
  1405. protocol.makeConnection(transport)
  1406. requestDeferred = protocol.request(
  1407. Request(b'GET', b'/', _boringHeaders, None, persistent=True))
  1408. requestDeferred.addCallback(quiescentResult.append)
  1409. protocol.dataReceived(
  1410. b"HTTP/1.1 200 OK\r\n"
  1411. b"Content-length: 0\r\n"
  1412. b"\r\n")
  1413. self.assertEqual(len(quiescentResult), 2)
  1414. self.assertIdentical(quiescentResult[0], protocol)
  1415. self.assertIsInstance(quiescentResult[1], Response)
  1416. def test_quiescentCallbackNotCalled(self):
  1417. """
  1418. If after a response is done the {HTTP11ClientProtocol} returns a
  1419. C{Connection: close} header in the response, the C{quiescentCallback}
  1420. is not called and the connection is lost.
  1421. """
  1422. quiescentResult = []
  1423. transport = StringTransport()
  1424. protocol = HTTP11ClientProtocol(quiescentResult.append)
  1425. protocol.makeConnection(transport)
  1426. requestDeferred = protocol.request(
  1427. Request(b'GET', b'/', _boringHeaders, None, persistent=True))
  1428. protocol.dataReceived(
  1429. b"HTTP/1.1 200 OK\r\n"
  1430. b"Content-length: 0\r\n"
  1431. b"Connection: close\r\n"
  1432. b"\r\n")
  1433. result = []
  1434. requestDeferred.addCallback(result.append)
  1435. response = result[0]
  1436. bodyProtocol = AccumulatingProtocol()
  1437. response.deliverBody(bodyProtocol)
  1438. bodyProtocol.closedReason.trap(ResponseDone)
  1439. self.assertEqual(quiescentResult, [])
  1440. self.assertTrue(transport.disconnecting)
  1441. def test_quiescentCallbackNotCalledNonPersistentQuery(self):
  1442. """
  1443. If the request was non-persistent (i.e. sent C{Connection: close}),
  1444. the C{quiescentCallback} is not called and the connection is lost.
  1445. """
  1446. quiescentResult = []
  1447. transport = StringTransport()
  1448. protocol = HTTP11ClientProtocol(quiescentResult.append)
  1449. protocol.makeConnection(transport)
  1450. requestDeferred = protocol.request(
  1451. Request(b'GET', b'/', _boringHeaders, None, persistent=False))
  1452. protocol.dataReceived(
  1453. b"HTTP/1.1 200 OK\r\n"
  1454. b"Content-length: 0\r\n"
  1455. b"\r\n")
  1456. result = []
  1457. requestDeferred.addCallback(result.append)
  1458. response = result[0]
  1459. bodyProtocol = AccumulatingProtocol()
  1460. response.deliverBody(bodyProtocol)
  1461. bodyProtocol.closedReason.trap(ResponseDone)
  1462. self.assertEqual(quiescentResult, [])
  1463. self.assertTrue(transport.disconnecting)
  1464. def test_quiescentCallbackThrows(self):
  1465. """
  1466. If C{quiescentCallback} throws an exception, the error is logged and
  1467. protocol is disconnected.
  1468. """
  1469. def callback(p):
  1470. raise ZeroDivisionError()
  1471. transport = StringTransport()
  1472. protocol = HTTP11ClientProtocol(callback)
  1473. protocol.makeConnection(transport)
  1474. requestDeferred = protocol.request(
  1475. Request(b'GET', b'/', _boringHeaders, None, persistent=True))
  1476. protocol.dataReceived(
  1477. b"HTTP/1.1 200 OK\r\n"
  1478. b"Content-length: 0\r\n"
  1479. b"\r\n")
  1480. result = []
  1481. requestDeferred.addCallback(result.append)
  1482. response = result[0]
  1483. bodyProtocol = AccumulatingProtocol()
  1484. response.deliverBody(bodyProtocol)
  1485. bodyProtocol.closedReason.trap(ResponseDone)
  1486. errors = self.flushLoggedErrors(ZeroDivisionError)
  1487. self.assertEqual(len(errors), 1)
  1488. self.assertTrue(transport.disconnecting)
  1489. def test_cancelBeforeResponse(self):
  1490. """
  1491. The L{Deferred} returned by L{HTTP11ClientProtocol.request} will fire
  1492. with a L{ResponseNeverReceived} failure containing a L{CancelledError}
  1493. exception if the request was cancelled before any response headers were
  1494. received.
  1495. """
  1496. transport = StringTransport()
  1497. protocol = HTTP11ClientProtocol()
  1498. protocol.makeConnection(transport)
  1499. result = protocol.request(Request(b'GET', b'/', _boringHeaders, None))
  1500. result.cancel()
  1501. self.assertTrue(transport.aborting)
  1502. return assertWrapperExceptionTypes(
  1503. self, result, ResponseNeverReceived, [CancelledError])
  1504. def test_cancelDuringResponse(self):
  1505. """
  1506. The L{Deferred} returned by L{HTTP11ClientProtocol.request} will fire
  1507. with a L{ResponseFailed} failure containing a L{CancelledError}
  1508. exception if the request was cancelled before all response headers were
  1509. received.
  1510. """
  1511. transport = StringTransport()
  1512. protocol = HTTP11ClientProtocol()
  1513. protocol.makeConnection(transport)
  1514. result = protocol.request(Request(b'GET', b'/', _boringHeaders, None))
  1515. protocol.dataReceived(b"HTTP/1.1 200 OK\r\n")
  1516. result.cancel()
  1517. self.assertTrue(transport.aborting)
  1518. return assertResponseFailed(self, result, [CancelledError])
  1519. def assertCancelDuringBodyProduction(self, producerLength):
  1520. """
  1521. The L{Deferred} returned by L{HTTP11ClientProtocol.request} will fire
  1522. with a L{RequestGenerationFailed} failure containing a
  1523. L{CancelledError} exception if the request was cancelled before a
  1524. C{bodyProducer} has finished producing.
  1525. """
  1526. transport = StringTransport()
  1527. protocol = HTTP11ClientProtocol()
  1528. protocol.makeConnection(transport)
  1529. producer = StringProducer(producerLength)
  1530. nonLocal = {'cancelled': False}
  1531. def cancel(ign):
  1532. nonLocal['cancelled'] = True
  1533. def startProducing(consumer):
  1534. producer.consumer = consumer
  1535. producer.finished = Deferred(cancel)
  1536. return producer.finished
  1537. producer.startProducing = startProducing
  1538. result = protocol.request(Request(b'POST', b'/bar', _boringHeaders,
  1539. producer))
  1540. producer.consumer.write(b'x' * 5)
  1541. result.cancel()
  1542. self.assertTrue(transport.aborting)
  1543. self.assertTrue(nonLocal['cancelled'])
  1544. return assertRequestGenerationFailed(self, result, [CancelledError])
  1545. def test_cancelDuringBodyProduction(self):
  1546. """
  1547. The L{Deferred} returned by L{HTTP11ClientProtocol.request} will fire
  1548. with a L{RequestGenerationFailed} failure containing a
  1549. L{CancelledError} exception if the request was cancelled before a
  1550. C{bodyProducer} with an explicit length has finished producing.
  1551. """
  1552. return self.assertCancelDuringBodyProduction(10)
  1553. def test_cancelDuringChunkedBodyProduction(self):
  1554. """
  1555. The L{Deferred} returned by L{HTTP11ClientProtocol.request} will fire
  1556. with a L{RequestGenerationFailed} failure containing a
  1557. L{CancelledError} exception if the request was cancelled before a
  1558. C{bodyProducer} with C{UNKNOWN_LENGTH} has finished producing.
  1559. """
  1560. return self.assertCancelDuringBodyProduction(UNKNOWN_LENGTH)
  1561. @implementer(IBodyProducer)
  1562. class StringProducer:
  1563. """
  1564. L{StringProducer} is a dummy body producer.
  1565. @ivar stopped: A flag which indicates whether or not C{stopProducing} has
  1566. been called.
  1567. @ivar consumer: After C{startProducing} is called, the value of the
  1568. C{consumer} argument to that method.
  1569. @ivar finished: After C{startProducing} is called, a L{Deferred} which was
  1570. returned by that method. L{StringProducer} will never fire this
  1571. L{Deferred}.
  1572. """
  1573. stopped = False
  1574. def __init__(self, length):
  1575. self.length = length
  1576. def startProducing(self, consumer):
  1577. self.consumer = consumer
  1578. self.finished = Deferred()
  1579. return self.finished
  1580. def stopProducing(self):
  1581. self.stopped = True
  1582. class RequestTests(TestCase):
  1583. """
  1584. Tests for L{Request}.
  1585. """
  1586. def setUp(self):
  1587. self.transport = StringTransport()
  1588. def test_sendSimplestRequest(self):
  1589. """
  1590. L{Request.writeTo} formats the request data and writes it to the given
  1591. transport.
  1592. """
  1593. Request(b'GET', b'/', _boringHeaders, None).writeTo(self.transport)
  1594. self.assertEqual(
  1595. self.transport.value(),
  1596. b"GET / HTTP/1.1\r\n"
  1597. b"Connection: close\r\n"
  1598. b"Host: example.com\r\n"
  1599. b"\r\n")
  1600. def test_sendSimplestPersistentRequest(self):
  1601. """
  1602. A pesistent request does not send 'Connection: close' header.
  1603. """
  1604. req = Request(b'GET', b'/', _boringHeaders, None, persistent=True)
  1605. req.writeTo(self.transport)
  1606. self.assertEqual(
  1607. self.transport.value(),
  1608. b"GET / HTTP/1.1\r\n"
  1609. b"Host: example.com\r\n"
  1610. b"\r\n")
  1611. def test_sendRequestHeaders(self):
  1612. """
  1613. L{Request.writeTo} formats header data and writes it to the given
  1614. transport.
  1615. """
  1616. headers = Headers({b'x-foo': [b'bar', b'baz'],
  1617. b'host': [b'example.com']})
  1618. Request(b'GET', b'/foo', headers, None).writeTo(self.transport)
  1619. lines = self.transport.value().split(b'\r\n')
  1620. self.assertEqual(lines[0], b"GET /foo HTTP/1.1")
  1621. self.assertEqual(lines[-2:], [b"", b""])
  1622. del lines[0], lines[-2:]
  1623. lines.sort()
  1624. self.assertEqual(
  1625. lines,
  1626. [b"Connection: close",
  1627. b"Host: example.com",
  1628. b"X-Foo: bar",
  1629. b"X-Foo: baz"])
  1630. def test_sendChunkedRequestBody(self):
  1631. """
  1632. L{Request.writeTo} uses chunked encoding to write data from the request
  1633. body producer to the given transport. It registers the request body
  1634. producer with the transport.
  1635. """
  1636. producer = StringProducer(UNKNOWN_LENGTH)
  1637. request = Request(b'POST', b'/bar', _boringHeaders, producer)
  1638. request.writeTo(self.transport)
  1639. self.assertNotIdentical(producer.consumer, None)
  1640. self.assertIdentical(self.transport.producer, producer)
  1641. self.assertTrue(self.transport.streaming)
  1642. self.assertEqual(
  1643. self.transport.value(),
  1644. b"POST /bar HTTP/1.1\r\n"
  1645. b"Connection: close\r\n"
  1646. b"Transfer-Encoding: chunked\r\n"
  1647. b"Host: example.com\r\n"
  1648. b"\r\n")
  1649. self.transport.clear()
  1650. producer.consumer.write(b'x' * 3)
  1651. producer.consumer.write(b'y' * 15)
  1652. producer.finished.callback(None)
  1653. self.assertIdentical(self.transport.producer, None)
  1654. self.assertEqual(
  1655. self.transport.value(),
  1656. b"3\r\n"
  1657. b"xxx\r\n"
  1658. b"f\r\n"
  1659. b"yyyyyyyyyyyyyyy\r\n"
  1660. b"0\r\n"
  1661. b"\r\n")
  1662. def test_sendChunkedRequestBodyWithError(self):
  1663. """
  1664. If L{Request} is created with a C{bodyProducer} without a known length
  1665. and the L{Deferred} returned from its C{startProducing} method fires
  1666. with a L{Failure}, the L{Deferred} returned by L{Request.writeTo} fires
  1667. with that L{Failure} and the body producer is unregistered from the
  1668. transport. The final zero-length chunk is not written to the
  1669. transport.
  1670. """
  1671. producer = StringProducer(UNKNOWN_LENGTH)
  1672. request = Request(b'POST', b'/bar', _boringHeaders, producer)
  1673. writeDeferred = request.writeTo(self.transport)
  1674. self.transport.clear()
  1675. producer.finished.errback(ArbitraryException())
  1676. def cbFailed(ignored):
  1677. self.assertEqual(self.transport.value(), b"")
  1678. self.assertIdentical(self.transport.producer, None)
  1679. d = self.assertFailure(writeDeferred, ArbitraryException)
  1680. d.addCallback(cbFailed)
  1681. return d
  1682. def test_sendRequestBodyWithLength(self):
  1683. """
  1684. If L{Request} is created with a C{bodyProducer} with a known length,
  1685. that length is sent as the value for the I{Content-Length} header and
  1686. chunked encoding is not used.
  1687. """
  1688. producer = StringProducer(3)
  1689. request = Request(b'POST', b'/bar', _boringHeaders, producer)
  1690. request.writeTo(self.transport)
  1691. self.assertNotIdentical(producer.consumer, None)
  1692. self.assertIdentical(self.transport.producer, producer)
  1693. self.assertTrue(self.transport.streaming)
  1694. self.assertEqual(
  1695. self.transport.value(),
  1696. b"POST /bar HTTP/1.1\r\n"
  1697. b"Connection: close\r\n"
  1698. b"Content-Length: 3\r\n"
  1699. b"Host: example.com\r\n"
  1700. b"\r\n")
  1701. self.transport.clear()
  1702. producer.consumer.write(b'abc')
  1703. producer.finished.callback(None)
  1704. self.assertIdentical(self.transport.producer, None)
  1705. self.assertEqual(self.transport.value(), b"abc")
  1706. def _sendRequestEmptyBodyWithLength(self, method):
  1707. """
  1708. Verify that the message generated by a L{Request} initialized with
  1709. the given method and C{None} as the C{bodyProducer} includes
  1710. I{Content-Length: 0} in the header.
  1711. @param method: The HTTP method issue in the request.
  1712. @type method: L{bytes}
  1713. """
  1714. request = Request(method, b"/foo", _boringHeaders, None)
  1715. request.writeTo(self.transport)
  1716. self.assertEqual(
  1717. self.transport.value(),
  1718. method + b" /foo HTTP/1.1\r\n"
  1719. b"Connection: close\r\n"
  1720. b"Content-Length: 0\r\n"
  1721. b"Host: example.com\r\n"
  1722. b"\r\n")
  1723. def test_sendPUTRequestEmptyBody(self):
  1724. """
  1725. If I{PUT} L{Request} is created without a C{bodyProducer},
  1726. I{Content-Length: 0} is included in the header and chunked
  1727. encoding is not used.
  1728. """
  1729. self._sendRequestEmptyBodyWithLength(b"PUT")
  1730. def test_sendPOSTRequestEmptyBody(self):
  1731. """
  1732. If I{POST} L{Request} is created without a C{bodyProducer},
  1733. I{Content-Length: 0} is included in the header and chunked
  1734. encoding is not used.
  1735. """
  1736. self._sendRequestEmptyBodyWithLength(b"POST")
  1737. def test_sendRequestBodyWithTooFewBytes(self):
  1738. """
  1739. If L{Request} is created with a C{bodyProducer} with a known length and
  1740. the producer does not produce that many bytes, the L{Deferred} returned
  1741. by L{Request.writeTo} fires with a L{Failure} wrapping a
  1742. L{WrongBodyLength} exception.
  1743. """
  1744. producer = StringProducer(3)
  1745. request = Request(b'POST', b'/bar', _boringHeaders, producer)
  1746. writeDeferred = request.writeTo(self.transport)
  1747. producer.consumer.write(b'ab')
  1748. producer.finished.callback(None)
  1749. self.assertIdentical(self.transport.producer, None)
  1750. return self.assertFailure(writeDeferred, WrongBodyLength)
  1751. def _sendRequestBodyWithTooManyBytesTest(self, finisher):
  1752. """
  1753. Verify that when too many bytes have been written by a body producer
  1754. and then the body producer's C{startProducing} L{Deferred} fires that
  1755. the producer is unregistered from the transport and that the
  1756. L{Deferred} returned from L{Request.writeTo} is fired with a L{Failure}
  1757. wrapping a L{WrongBodyLength}.
  1758. @param finisher: A callable which will be invoked with the body
  1759. producer after too many bytes have been written to the transport.
  1760. It should fire the startProducing Deferred somehow.
  1761. """
  1762. producer = StringProducer(3)
  1763. request = Request(b'POST', b'/bar', _boringHeaders, producer)
  1764. writeDeferred = request.writeTo(self.transport)
  1765. producer.consumer.write(b'ab')
  1766. # The producer hasn't misbehaved yet, so it shouldn't have been
  1767. # stopped.
  1768. self.assertFalse(producer.stopped)
  1769. producer.consumer.write(b'cd')
  1770. # Now the producer *has* misbehaved, so we should have tried to
  1771. # make it stop.
  1772. self.assertTrue(producer.stopped)
  1773. # The transport should have had the producer unregistered from it as
  1774. # well.
  1775. self.assertIdentical(self.transport.producer, None)
  1776. def cbFailed(exc):
  1777. # The "cd" should not have been written to the transport because
  1778. # the request can now locally be recognized to be invalid. If we
  1779. # had written the extra bytes, the server could have decided to
  1780. # start processing the request, which would be bad since we're
  1781. # going to indicate failure locally.
  1782. self.assertEqual(
  1783. self.transport.value(),
  1784. b"POST /bar HTTP/1.1\r\n"
  1785. b"Connection: close\r\n"
  1786. b"Content-Length: 3\r\n"
  1787. b"Host: example.com\r\n"
  1788. b"\r\n"
  1789. b"ab")
  1790. self.transport.clear()
  1791. # Subsequent writes should be ignored, as should firing the
  1792. # Deferred returned from startProducing.
  1793. self.assertRaises(ExcessWrite, producer.consumer.write, b'ef')
  1794. # Likewise, if the Deferred returned from startProducing fires,
  1795. # this should more or less be ignored (aside from possibly logging
  1796. # an error).
  1797. finisher(producer)
  1798. # There should have been nothing further written to the transport.
  1799. self.assertEqual(self.transport.value(), b"")
  1800. d = self.assertFailure(writeDeferred, WrongBodyLength)
  1801. d.addCallback(cbFailed)
  1802. return d
  1803. def test_sendRequestBodyWithTooManyBytes(self):
  1804. """
  1805. If L{Request} is created with a C{bodyProducer} with a known length and
  1806. the producer tries to produce more than than many bytes, the
  1807. L{Deferred} returned by L{Request.writeTo} fires with a L{Failure}
  1808. wrapping a L{WrongBodyLength} exception.
  1809. """
  1810. def finisher(producer):
  1811. producer.finished.callback(None)
  1812. return self._sendRequestBodyWithTooManyBytesTest(finisher)
  1813. def test_sendRequestBodyErrorWithTooManyBytes(self):
  1814. """
  1815. If L{Request} is created with a C{bodyProducer} with a known length and
  1816. the producer tries to produce more than than many bytes, the
  1817. L{Deferred} returned by L{Request.writeTo} fires with a L{Failure}
  1818. wrapping a L{WrongBodyLength} exception.
  1819. """
  1820. def finisher(producer):
  1821. producer.finished.errback(ArbitraryException())
  1822. errors = self.flushLoggedErrors(ArbitraryException)
  1823. self.assertEqual(len(errors), 1)
  1824. return self._sendRequestBodyWithTooManyBytesTest(finisher)
  1825. def test_sendRequestBodyErrorWithConsumerError(self):
  1826. """
  1827. Though there should be no way for the internal C{finishedConsuming}
  1828. L{Deferred} in L{Request._writeToBodyProducerContentLength} to fire a
  1829. L{Failure} after the C{finishedProducing} L{Deferred} has fired, in
  1830. case this does happen, the error should be logged with a message about
  1831. how there's probably a bug in L{Request}.
  1832. This is a whitebox test.
  1833. """
  1834. producer = StringProducer(3)
  1835. request = Request(b'POST', b'/bar', _boringHeaders, producer)
  1836. request.writeTo(self.transport)
  1837. finishedConsuming = producer.consumer._finished
  1838. producer.consumer.write(b'abc')
  1839. producer.finished.callback(None)
  1840. finishedConsuming.errback(ArbitraryException())
  1841. self.assertEqual(len(self.flushLoggedErrors(ArbitraryException)), 1)
  1842. def _sendRequestBodyFinishedEarlyThenTooManyBytes(self, finisher):
  1843. """
  1844. Verify that if the body producer fires its Deferred and then keeps
  1845. writing to the consumer that the extra writes are ignored and the
  1846. L{Deferred} returned by L{Request.writeTo} fires with a L{Failure}
  1847. wrapping the most appropriate exception type.
  1848. """
  1849. producer = StringProducer(3)
  1850. request = Request(b'POST', b'/bar', _boringHeaders, producer)
  1851. writeDeferred = request.writeTo(self.transport)
  1852. producer.consumer.write(b'ab')
  1853. finisher(producer)
  1854. self.assertIdentical(self.transport.producer, None)
  1855. self.transport.clear()
  1856. self.assertRaises(ExcessWrite, producer.consumer.write, b'cd')
  1857. self.assertEqual(self.transport.value(), b"")
  1858. return writeDeferred
  1859. def test_sendRequestBodyFinishedEarlyThenTooManyBytes(self):
  1860. """
  1861. If the request body producer indicates it is done by firing the
  1862. L{Deferred} returned from its C{startProducing} method but then goes on
  1863. to write too many bytes, the L{Deferred} returned by {Request.writeTo}
  1864. fires with a L{Failure} wrapping L{WrongBodyLength}.
  1865. """
  1866. def finisher(producer):
  1867. producer.finished.callback(None)
  1868. return self.assertFailure(
  1869. self._sendRequestBodyFinishedEarlyThenTooManyBytes(finisher),
  1870. WrongBodyLength)
  1871. def test_sendRequestBodyErroredEarlyThenTooManyBytes(self):
  1872. """
  1873. If the request body producer indicates an error by firing the
  1874. L{Deferred} returned from its C{startProducing} method but then goes on
  1875. to write too many bytes, the L{Deferred} returned by {Request.writeTo}
  1876. fires with that L{Failure} and L{WrongBodyLength} is logged.
  1877. """
  1878. def finisher(producer):
  1879. producer.finished.errback(ArbitraryException())
  1880. return self.assertFailure(
  1881. self._sendRequestBodyFinishedEarlyThenTooManyBytes(finisher),
  1882. ArbitraryException)
  1883. def test_sendChunkedRequestBodyFinishedThenWriteMore(self, _with=None):
  1884. """
  1885. If the request body producer with an unknown length tries to write
  1886. after firing the L{Deferred} returned by its C{startProducing} method,
  1887. the C{write} call raises an exception and does not write anything to
  1888. the underlying transport.
  1889. """
  1890. producer = StringProducer(UNKNOWN_LENGTH)
  1891. request = Request(b'POST', b'/bar', _boringHeaders, producer)
  1892. writeDeferred = request.writeTo(self.transport)
  1893. producer.finished.callback(_with)
  1894. self.transport.clear()
  1895. self.assertRaises(ExcessWrite, producer.consumer.write, b'foo')
  1896. self.assertEqual(self.transport.value(), b"")
  1897. return writeDeferred
  1898. def test_sendChunkedRequestBodyFinishedWithErrorThenWriteMore(self):
  1899. """
  1900. If the request body producer with an unknown length tries to write
  1901. after firing the L{Deferred} returned by its C{startProducing} method
  1902. with a L{Failure}, the C{write} call raises an exception and does not
  1903. write anything to the underlying transport.
  1904. """
  1905. d = self.test_sendChunkedRequestBodyFinishedThenWriteMore(
  1906. Failure(ArbitraryException()))
  1907. return self.assertFailure(d, ArbitraryException)
  1908. def test_sendRequestBodyWithError(self):
  1909. """
  1910. If the L{Deferred} returned from the C{startProducing} method of the
  1911. L{IBodyProducer} passed to L{Request} fires with a L{Failure}, the
  1912. L{Deferred} returned from L{Request.writeTo} fails with that
  1913. L{Failure}.
  1914. """
  1915. producer = StringProducer(5)
  1916. request = Request(b'POST', b'/bar', _boringHeaders, producer)
  1917. writeDeferred = request.writeTo(self.transport)
  1918. # Sanity check - the producer should be registered with the underlying
  1919. # transport.
  1920. self.assertIdentical(self.transport.producer, producer)
  1921. self.assertTrue(self.transport.streaming)
  1922. producer.consumer.write(b'ab')
  1923. self.assertEqual(
  1924. self.transport.value(),
  1925. b"POST /bar HTTP/1.1\r\n"
  1926. b"Connection: close\r\n"
  1927. b"Content-Length: 5\r\n"
  1928. b"Host: example.com\r\n"
  1929. b"\r\n"
  1930. b"ab")
  1931. self.assertFalse(self.transport.disconnecting)
  1932. producer.finished.errback(Failure(ArbitraryException()))
  1933. # Disconnection is handled by a higher level. Request should leave the
  1934. # transport alone in this case.
  1935. self.assertFalse(self.transport.disconnecting)
  1936. # Oh. Except it should unregister the producer that it registered.
  1937. self.assertIdentical(self.transport.producer, None)
  1938. return self.assertFailure(writeDeferred, ArbitraryException)
  1939. def test_hostHeaderRequired(self):
  1940. """
  1941. L{Request.writeTo} raises L{BadHeaders} if there is not exactly one
  1942. I{Host} header and writes nothing to the given transport.
  1943. """
  1944. request = Request(b'GET', b'/', Headers({}), None)
  1945. self.assertRaises(BadHeaders, request.writeTo, self.transport)
  1946. self.assertEqual(self.transport.value(), b'')
  1947. request = Request(b'GET', b'/',
  1948. Headers({b'Host': [b'example.com', b'example.org']}), None)
  1949. self.assertRaises(BadHeaders, request.writeTo, self.transport)
  1950. self.assertEqual(self.transport.value(), b'')
  1951. def test_stopWriting(self):
  1952. """
  1953. L{Request.stopWriting} calls its body producer's C{stopProducing}
  1954. method.
  1955. """
  1956. producer = StringProducer(3)
  1957. request = Request(b'GET', b'/', _boringHeaders, producer)
  1958. request.writeTo(self.transport)
  1959. self.assertFalse(producer.stopped)
  1960. request.stopWriting()
  1961. self.assertTrue(producer.stopped)
  1962. def test_brokenStopProducing(self):
  1963. """
  1964. If the body producer's C{stopProducing} method raises an exception,
  1965. L{Request.stopWriting} logs it and does not re-raise it.
  1966. """
  1967. producer = StringProducer(3)
  1968. def brokenStopProducing():
  1969. raise ArbitraryException(u"stopProducing is busted")
  1970. producer.stopProducing = brokenStopProducing
  1971. request = Request(b'GET', b'/', _boringHeaders, producer)
  1972. request.writeTo(self.transport)
  1973. request.stopWriting()
  1974. self.assertEqual(
  1975. len(self.flushLoggedErrors(ArbitraryException)), 1)
  1976. class LengthEnforcingConsumerTests(TestCase):
  1977. """
  1978. Tests for L{LengthEnforcingConsumer}.
  1979. """
  1980. def setUp(self):
  1981. self.result = Deferred()
  1982. self.producer = StringProducer(10)
  1983. self.transport = StringTransport()
  1984. self.enforcer = LengthEnforcingConsumer(
  1985. self.producer, self.transport, self.result)
  1986. def test_write(self):
  1987. """
  1988. L{LengthEnforcingConsumer.write} calls the wrapped consumer's C{write}
  1989. method with the bytes it is passed as long as there are fewer of them
  1990. than the C{length} attribute indicates remain to be received.
  1991. """
  1992. self.enforcer.write(b'abc')
  1993. self.assertEqual(self.transport.value(), b'abc')
  1994. self.transport.clear()
  1995. self.enforcer.write(b'def')
  1996. self.assertEqual(self.transport.value(), b'def')
  1997. def test_finishedEarly(self):
  1998. """
  1999. L{LengthEnforcingConsumer._noMoreWritesExpected} raises
  2000. L{WrongBodyLength} if it is called before the indicated number of bytes
  2001. have been written.
  2002. """
  2003. self.enforcer.write(b'x' * 9)
  2004. self.assertRaises(WrongBodyLength, self.enforcer._noMoreWritesExpected)
  2005. def test_writeTooMany(self, _unregisterAfter=False):
  2006. """
  2007. If it is called with a total number of bytes exceeding the indicated
  2008. limit passed to L{LengthEnforcingConsumer.__init__},
  2009. L{LengthEnforcingConsumer.write} fires the L{Deferred} with a
  2010. L{Failure} wrapping a L{WrongBodyLength} and also calls the
  2011. C{stopProducing} method of the producer.
  2012. """
  2013. self.enforcer.write(b'x' * 10)
  2014. self.assertFalse(self.producer.stopped)
  2015. self.enforcer.write(b'x')
  2016. self.assertTrue(self.producer.stopped)
  2017. if _unregisterAfter:
  2018. self.enforcer._noMoreWritesExpected()
  2019. return self.assertFailure(self.result, WrongBodyLength)
  2020. def test_writeAfterNoMoreExpected(self):
  2021. """
  2022. If L{LengthEnforcingConsumer.write} is called after
  2023. L{LengthEnforcingConsumer._noMoreWritesExpected}, it calls the
  2024. producer's C{stopProducing} method and raises L{ExcessWrite}.
  2025. """
  2026. self.enforcer.write(b'x' * 10)
  2027. self.enforcer._noMoreWritesExpected()
  2028. self.assertFalse(self.producer.stopped)
  2029. self.assertRaises(ExcessWrite, self.enforcer.write, b'x')
  2030. self.assertTrue(self.producer.stopped)
  2031. def test_finishedLate(self):
  2032. """
  2033. L{LengthEnforcingConsumer._noMoreWritesExpected} does nothing (in
  2034. particular, it does not raise any exception) if called after too many
  2035. bytes have been passed to C{write}.
  2036. """
  2037. return self.test_writeTooMany(True)
  2038. def test_finished(self):
  2039. """
  2040. If L{LengthEnforcingConsumer._noMoreWritesExpected} is called after
  2041. the correct number of bytes have been written it returns L{None}.
  2042. """
  2043. self.enforcer.write(b'x' * 10)
  2044. self.assertIdentical(self.enforcer._noMoreWritesExpected(), None)
  2045. def test_stopProducingRaises(self):
  2046. """
  2047. If L{LengthEnforcingConsumer.write} calls the producer's
  2048. C{stopProducing} because too many bytes were written and the
  2049. C{stopProducing} method raises an exception, the exception is logged
  2050. and the L{LengthEnforcingConsumer} still errbacks the finished
  2051. L{Deferred}.
  2052. """
  2053. def brokenStopProducing():
  2054. StringProducer.stopProducing(self.producer)
  2055. raise ArbitraryException(u"stopProducing is busted")
  2056. self.producer.stopProducing = brokenStopProducing
  2057. def cbFinished(ignored):
  2058. self.assertEqual(
  2059. len(self.flushLoggedErrors(ArbitraryException)), 1)
  2060. d = self.test_writeTooMany()
  2061. d.addCallback(cbFinished)
  2062. return d
  2063. class RequestBodyConsumerTests(TestCase):
  2064. """
  2065. Tests for L{ChunkedEncoder} which sits between an L{ITransport} and a
  2066. request/response body producer and chunked encodes everything written to
  2067. it.
  2068. """
  2069. def test_interface(self):
  2070. """
  2071. L{ChunkedEncoder} instances provide L{IConsumer}.
  2072. """
  2073. self.assertTrue(
  2074. verifyObject(IConsumer, ChunkedEncoder(StringTransport())))
  2075. def test_write(self):
  2076. """
  2077. L{ChunkedEncoder.write} writes to the transport the chunked encoded
  2078. form of the bytes passed to it.
  2079. """
  2080. transport = StringTransport()
  2081. encoder = ChunkedEncoder(transport)
  2082. encoder.write(b'foo')
  2083. self.assertEqual(transport.value(), b'3\r\nfoo\r\n')
  2084. transport.clear()
  2085. encoder.write(b'x' * 16)
  2086. self.assertEqual(transport.value(), b'10\r\n' + b'x' * 16 + b'\r\n')
  2087. def test_producerRegistration(self):
  2088. """
  2089. L{ChunkedEncoder.registerProducer} registers the given streaming
  2090. producer with its transport and L{ChunkedEncoder.unregisterProducer}
  2091. writes a zero-length chunk to its transport and unregisters the
  2092. transport's producer.
  2093. """
  2094. transport = StringTransport()
  2095. producer = object()
  2096. encoder = ChunkedEncoder(transport)
  2097. encoder.registerProducer(producer, True)
  2098. self.assertIdentical(transport.producer, producer)
  2099. self.assertTrue(transport.streaming)
  2100. encoder.unregisterProducer()
  2101. self.assertIdentical(transport.producer, None)
  2102. self.assertEqual(transport.value(), b'0\r\n\r\n')
  2103. class TransportProxyProducerTests(TestCase):
  2104. """
  2105. Tests for L{TransportProxyProducer} which proxies the L{IPushProducer}
  2106. interface of a transport.
  2107. """
  2108. def test_interface(self):
  2109. """
  2110. L{TransportProxyProducer} instances provide L{IPushProducer}.
  2111. """
  2112. self.assertTrue(
  2113. verifyObject(IPushProducer, TransportProxyProducer(None)))
  2114. def test_stopProxyingUnreferencesProducer(self):
  2115. """
  2116. L{TransportProxyProducer._stopProxying} drops the reference to the
  2117. wrapped L{IPushProducer} provider.
  2118. """
  2119. transport = StringTransport()
  2120. proxy = TransportProxyProducer(transport)
  2121. self.assertIdentical(proxy._producer, transport)
  2122. proxy._stopProxying()
  2123. self.assertIdentical(proxy._producer, None)
  2124. def test_resumeProducing(self):
  2125. """
  2126. L{TransportProxyProducer.resumeProducing} calls the wrapped
  2127. transport's C{resumeProducing} method unless told to stop proxying.
  2128. """
  2129. transport = StringTransport()
  2130. transport.pauseProducing()
  2131. proxy = TransportProxyProducer(transport)
  2132. # The transport should still be paused.
  2133. self.assertEqual(transport.producerState, u'paused')
  2134. proxy.resumeProducing()
  2135. # The transport should now be resumed.
  2136. self.assertEqual(transport.producerState, u'producing')
  2137. transport.pauseProducing()
  2138. proxy._stopProxying()
  2139. # The proxy should no longer do anything to the transport.
  2140. proxy.resumeProducing()
  2141. self.assertEqual(transport.producerState, u'paused')
  2142. def test_pauseProducing(self):
  2143. """
  2144. L{TransportProxyProducer.pauseProducing} calls the wrapped transport's
  2145. C{pauseProducing} method unless told to stop proxying.
  2146. """
  2147. transport = StringTransport()
  2148. proxy = TransportProxyProducer(transport)
  2149. # The transport should still be producing.
  2150. self.assertEqual(transport.producerState, u'producing')
  2151. proxy.pauseProducing()
  2152. # The transport should now be paused.
  2153. self.assertEqual(transport.producerState, u'paused')
  2154. transport.resumeProducing()
  2155. proxy._stopProxying()
  2156. # The proxy should no longer do anything to the transport.
  2157. proxy.pauseProducing()
  2158. self.assertEqual(transport.producerState, u'producing')
  2159. def test_stopProducing(self):
  2160. """
  2161. L{TransportProxyProducer.stopProducing} calls the wrapped transport's
  2162. C{stopProducing} method unless told to stop proxying.
  2163. """
  2164. transport = StringTransport()
  2165. proxy = TransportProxyProducer(transport)
  2166. # The transport should still be producing.
  2167. self.assertEqual(transport.producerState, u'producing')
  2168. proxy.stopProducing()
  2169. # The transport should now be stopped.
  2170. self.assertEqual(transport.producerState, u'stopped')
  2171. transport = StringTransport()
  2172. proxy = TransportProxyProducer(transport)
  2173. proxy._stopProxying()
  2174. proxy.stopProducing()
  2175. # The transport should not have been stopped.
  2176. self.assertEqual(transport.producerState, u'producing')
  2177. class ResponseTests(TestCase):
  2178. """
  2179. Tests for L{Response}.
  2180. """
  2181. def test_verifyInterface(self):
  2182. """
  2183. L{Response} instances provide L{IResponse}.
  2184. """
  2185. response = justTransportResponse(StringTransport())
  2186. self.assertTrue(verifyObject(IResponse, response))
  2187. def test_makeConnection(self):
  2188. """
  2189. The L{IProtocol} provider passed to L{Response.deliverBody} has its
  2190. C{makeConnection} method called with an L{IPushProducer} provider
  2191. hooked up to the response as an argument.
  2192. """
  2193. producers = []
  2194. transport = StringTransport()
  2195. class SomeProtocol(Protocol):
  2196. def makeConnection(self, producer):
  2197. producers.append(producer)
  2198. consumer = SomeProtocol()
  2199. response = justTransportResponse(transport)
  2200. response.deliverBody(consumer)
  2201. [theProducer] = producers
  2202. theProducer.pauseProducing()
  2203. self.assertEqual(transport.producerState, u'paused')
  2204. theProducer.resumeProducing()
  2205. self.assertEqual(transport.producerState, u'producing')
  2206. def test_dataReceived(self):
  2207. """
  2208. The L{IProtocol} provider passed to L{Response.deliverBody} has its
  2209. C{dataReceived} method called with bytes received as part of the
  2210. response body.
  2211. """
  2212. bytes = []
  2213. class ListConsumer(Protocol):
  2214. def dataReceived(self, data):
  2215. bytes.append(data)
  2216. consumer = ListConsumer()
  2217. response = justTransportResponse(StringTransport())
  2218. response.deliverBody(consumer)
  2219. response._bodyDataReceived(b'foo')
  2220. self.assertEqual(bytes, [b'foo'])
  2221. def test_connectionLost(self):
  2222. """
  2223. The L{IProtocol} provider passed to L{Response.deliverBody} has its
  2224. C{connectionLost} method called with a L{Failure} wrapping
  2225. L{ResponseDone} when the response's C{_bodyDataFinished} method is
  2226. called.
  2227. """
  2228. lost = []
  2229. class ListConsumer(Protocol):
  2230. def connectionLost(self, reason):
  2231. lost.append(reason)
  2232. consumer = ListConsumer()
  2233. response = justTransportResponse(StringTransport())
  2234. response.deliverBody(consumer)
  2235. response._bodyDataFinished()
  2236. lost[0].trap(ResponseDone)
  2237. self.assertEqual(len(lost), 1)
  2238. # The protocol reference should be dropped, too, to facilitate GC or
  2239. # whatever.
  2240. self.assertIdentical(response._bodyProtocol, None)
  2241. def test_bufferEarlyData(self):
  2242. """
  2243. If data is delivered to the L{Response} before a protocol is registered
  2244. with C{deliverBody}, that data is buffered until the protocol is
  2245. registered and then is delivered.
  2246. """
  2247. bytes = []
  2248. class ListConsumer(Protocol):
  2249. def dataReceived(self, data):
  2250. bytes.append(data)
  2251. protocol = ListConsumer()
  2252. response = justTransportResponse(StringTransport())
  2253. response._bodyDataReceived(b'foo')
  2254. response._bodyDataReceived(b'bar')
  2255. response.deliverBody(protocol)
  2256. response._bodyDataReceived(b'baz')
  2257. self.assertEqual(bytes, [b'foo', b'bar', b'baz'])
  2258. # Make sure the implementation-detail-byte-buffer is cleared because
  2259. # not clearing it wastes memory.
  2260. self.assertIdentical(response._bodyBuffer, None)
  2261. def test_multipleStartProducingFails(self):
  2262. """
  2263. L{Response.deliverBody} raises L{RuntimeError} if called more than
  2264. once.
  2265. """
  2266. response = justTransportResponse(StringTransport())
  2267. response.deliverBody(Protocol())
  2268. self.assertRaises(RuntimeError, response.deliverBody, Protocol())
  2269. def test_startProducingAfterFinishedFails(self):
  2270. """
  2271. L{Response.deliverBody} raises L{RuntimeError} if called after
  2272. L{Response._bodyDataFinished}.
  2273. """
  2274. response = justTransportResponse(StringTransport())
  2275. response.deliverBody(Protocol())
  2276. response._bodyDataFinished()
  2277. self.assertRaises(RuntimeError, response.deliverBody, Protocol())
  2278. def test_bodyDataReceivedAfterFinishedFails(self):
  2279. """
  2280. L{Response._bodyDataReceived} raises L{RuntimeError} if called after
  2281. L{Response._bodyDataFinished} but before L{Response.deliverBody}.
  2282. """
  2283. response = justTransportResponse(StringTransport())
  2284. response._bodyDataFinished()
  2285. self.assertRaises(RuntimeError, response._bodyDataReceived, b'foo')
  2286. def test_bodyDataReceivedAfterDeliveryFails(self):
  2287. """
  2288. L{Response._bodyDataReceived} raises L{RuntimeError} if called after
  2289. L{Response._bodyDataFinished} and after L{Response.deliverBody}.
  2290. """
  2291. response = justTransportResponse(StringTransport())
  2292. response._bodyDataFinished()
  2293. response.deliverBody(Protocol())
  2294. self.assertRaises(RuntimeError, response._bodyDataReceived, b'foo')
  2295. def test_bodyDataFinishedAfterFinishedFails(self):
  2296. """
  2297. L{Response._bodyDataFinished} raises L{RuntimeError} if called more
  2298. than once.
  2299. """
  2300. response = justTransportResponse(StringTransport())
  2301. response._bodyDataFinished()
  2302. self.assertRaises(RuntimeError, response._bodyDataFinished)
  2303. def test_bodyDataFinishedAfterDeliveryFails(self):
  2304. """
  2305. L{Response._bodyDataFinished} raises L{RuntimeError} if called after
  2306. the body has been delivered.
  2307. """
  2308. response = justTransportResponse(StringTransport())
  2309. response._bodyDataFinished()
  2310. response.deliverBody(Protocol())
  2311. self.assertRaises(RuntimeError, response._bodyDataFinished)
  2312. def test_transportResumed(self):
  2313. """
  2314. L{Response.deliverBody} resumes the HTTP connection's transport
  2315. after passing it to the consumer's C{makeConnection} method.
  2316. """
  2317. transportState = []
  2318. class ListConsumer(Protocol):
  2319. def makeConnection(self, transport):
  2320. transportState.append(transport.producerState)
  2321. transport = StringTransport()
  2322. transport.pauseProducing()
  2323. protocol = ListConsumer()
  2324. response = justTransportResponse(transport)
  2325. self.assertEqual(transport.producerState, u'paused')
  2326. response.deliverBody(protocol)
  2327. self.assertEqual(transportState, [u'paused'])
  2328. self.assertEqual(transport.producerState, u'producing')
  2329. def test_bodyDataFinishedBeforeStartProducing(self):
  2330. """
  2331. If the entire body is delivered to the L{Response} before the
  2332. response's C{deliverBody} method is called, the protocol passed to
  2333. C{deliverBody} is immediately given the body data and then
  2334. disconnected.
  2335. """
  2336. transport = StringTransport()
  2337. response = justTransportResponse(transport)
  2338. response._bodyDataReceived(b'foo')
  2339. response._bodyDataReceived(b'bar')
  2340. response._bodyDataFinished()
  2341. protocol = AccumulatingProtocol()
  2342. response.deliverBody(protocol)
  2343. self.assertEqual(protocol.data, b'foobar')
  2344. protocol.closedReason.trap(ResponseDone)
  2345. def test_finishedWithErrorWhenConnected(self):
  2346. """
  2347. The L{Failure} passed to L{Response._bodyDataFinished} when the response
  2348. is in the I{connected} state is passed to the C{connectionLost} method
  2349. of the L{IProtocol} provider passed to the L{Response}'s
  2350. C{deliverBody} method.
  2351. """
  2352. transport = StringTransport()
  2353. response = justTransportResponse(transport)
  2354. protocol = AccumulatingProtocol()
  2355. response.deliverBody(protocol)
  2356. # Sanity check - this test is for the connected state
  2357. self.assertEqual(response._state, u'CONNECTED')
  2358. response._bodyDataFinished(Failure(ArbitraryException()))
  2359. protocol.closedReason.trap(ArbitraryException)
  2360. def test_finishedWithErrorWhenInitial(self):
  2361. """
  2362. The L{Failure} passed to L{Response._bodyDataFinished} when the response
  2363. is in the I{initial} state is passed to the C{connectionLost} method of
  2364. the L{IProtocol} provider passed to the L{Response}'s C{deliverBody}
  2365. method.
  2366. """
  2367. transport = StringTransport()
  2368. response = justTransportResponse(transport)
  2369. # Sanity check - this test is for the initial state
  2370. self.assertEqual(response._state, u'INITIAL')
  2371. response._bodyDataFinished(Failure(ArbitraryException()))
  2372. protocol = AccumulatingProtocol()
  2373. response.deliverBody(protocol)
  2374. protocol.closedReason.trap(ArbitraryException)