|
13 | 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14 | 14 | # See the License for the specific language governing permissions and
|
15 | 15 | # limitations under the License.
|
16 |
| - |
17 | 16 | import logging
|
18 | 17 | import urllib
|
19 | 18 | from io import BytesIO
|
|
38 | 37 |
|
39 | 38 | from OpenSSL import SSL
|
40 | 39 | from OpenSSL.SSL import VERIFY_NONE
|
41 |
| -from twisted.internet import defer, protocol, ssl |
| 40 | +from twisted.internet import defer, error as twisted_error, protocol, ssl |
42 | 41 | from twisted.internet.interfaces import (
|
43 | 42 | IReactorPluggableNameResolver,
|
44 | 43 | IResolutionReceiver,
|
45 | 44 | )
|
46 | 45 | from twisted.internet.task import Cooperator
|
47 | 46 | from twisted.python.failure import Failure
|
48 | 47 | from twisted.web._newclient import ResponseDone
|
49 |
| -from twisted.web.client import Agent, HTTPConnectionPool, readBody |
| 48 | +from twisted.web.client import ( |
| 49 | + Agent, |
| 50 | + HTTPConnectionPool, |
| 51 | + ResponseNeverReceived, |
| 52 | + readBody, |
| 53 | +) |
50 | 54 | from twisted.web.http import PotentialDataLoss
|
51 | 55 | from twisted.web.http_headers import Headers
|
52 | 56 | from twisted.web.iweb import IResponse
|
53 | 57 |
|
54 | 58 | from synapse.api.errors import Codes, HttpResponseException, SynapseError
|
55 |
| -from synapse.http import ( |
56 |
| - QuieterFileBodyProducer, |
57 |
| - cancelled_to_request_timed_out_error, |
58 |
| - redact_uri, |
59 |
| -) |
| 59 | +from synapse.http import QuieterFileBodyProducer, RequestTimedOutError, redact_uri |
60 | 60 | from synapse.http.proxyagent import ProxyAgent
|
61 | 61 | from synapse.logging.context import make_deferred_yieldable
|
62 | 62 | from synapse.logging.opentracing import set_tag, start_active_span, tags
|
@@ -332,8 +332,6 @@ async def request(
|
332 | 332 | RequestTimedOutError if the request times out before the headers are read
|
333 | 333 |
|
334 | 334 | """
|
335 |
| - # A small wrapper around self.agent.request() so we can easily attach |
336 |
| - # counters to it |
337 | 335 | outgoing_requests_counter.labels(method).inc()
|
338 | 336 |
|
339 | 337 | # log request but strip `access_token` (AS requests for example include this)
|
@@ -362,15 +360,17 @@ async def request(
|
362 | 360 | data=body_producer,
|
363 | 361 | headers=headers,
|
364 | 362 | **self._extra_treq_args
|
365 |
| - ) |
| 363 | + ) # type: defer.Deferred |
| 364 | + |
366 | 365 | # we use our own timeout mechanism rather than treq's as a workaround
|
367 | 366 | # for https://twistedmatrix.com/trac/ticket/9534.
|
368 | 367 | request_deferred = timeout_deferred(
|
369 |
| - request_deferred, |
370 |
| - 60, |
371 |
| - self.hs.get_reactor(), |
372 |
| - cancelled_to_request_timed_out_error, |
| 368 | + request_deferred, 60, self.hs.get_reactor(), |
373 | 369 | )
|
| 370 | + |
| 371 | + # turn timeouts into RequestTimedOutErrors |
| 372 | + request_deferred.addErrback(_timeout_to_request_timed_out_error) |
| 373 | + |
374 | 374 | response = await make_deferred_yieldable(request_deferred)
|
375 | 375 |
|
376 | 376 | incoming_responses_counter.labels(method, response.code).inc()
|
@@ -410,7 +410,7 @@ async def post_urlencoded_get_json(
|
410 | 410 | parsed json
|
411 | 411 |
|
412 | 412 | Raises:
|
413 |
| - RequestTimedOutException: if there is a timeout before the response headers |
| 413 | + RequestTimedOutError: if there is a timeout before the response headers |
414 | 414 | are received. Note there is currently no timeout on reading the response
|
415 | 415 | body.
|
416 | 416 |
|
@@ -461,7 +461,7 @@ async def post_json_get_json(
|
461 | 461 | parsed json
|
462 | 462 |
|
463 | 463 | Raises:
|
464 |
| - RequestTimedOutException: if there is a timeout before the response headers |
| 464 | + RequestTimedOutError: if there is a timeout before the response headers |
465 | 465 | are received. Note there is currently no timeout on reading the response
|
466 | 466 | body.
|
467 | 467 |
|
@@ -506,7 +506,7 @@ async def get_json(
|
506 | 506 | Returns:
|
507 | 507 | Succeeds when we get a 2xx HTTP response, with the HTTP body as JSON.
|
508 | 508 | Raises:
|
509 |
| - RequestTimedOutException: if there is a timeout before the response headers |
| 509 | + RequestTimedOutError: if there is a timeout before the response headers |
510 | 510 | are received. Note there is currently no timeout on reading the response
|
511 | 511 | body.
|
512 | 512 |
|
@@ -538,7 +538,7 @@ async def put_json(
|
538 | 538 | Returns:
|
539 | 539 | Succeeds when we get a 2xx HTTP response, with the HTTP body as JSON.
|
540 | 540 | Raises:
|
541 |
| - RequestTimedOutException: if there is a timeout before the response headers |
| 541 | + RequestTimedOutError: if there is a timeout before the response headers |
542 | 542 | are received. Note there is currently no timeout on reading the response
|
543 | 543 | body.
|
544 | 544 |
|
@@ -586,7 +586,7 @@ async def get_raw(
|
586 | 586 | Succeeds when we get a 2xx HTTP response, with the
|
587 | 587 | HTTP body as bytes.
|
588 | 588 | Raises:
|
589 |
| - RequestTimedOutException: if there is a timeout before the response headers |
| 589 | + RequestTimedOutError: if there is a timeout before the response headers |
590 | 590 | are received. Note there is currently no timeout on reading the response
|
591 | 591 | body.
|
592 | 592 |
|
@@ -631,7 +631,7 @@ async def get_file(
|
631 | 631 | headers, absolute URI of the response and HTTP response code.
|
632 | 632 |
|
633 | 633 | Raises:
|
634 |
| - RequestTimedOutException: if there is a timeout before the response headers |
| 634 | + RequestTimedOutError: if there is a timeout before the response headers |
635 | 635 | are received. Note there is currently no timeout on reading the response
|
636 | 636 | body.
|
637 | 637 |
|
@@ -684,6 +684,18 @@ async def get_file(
|
684 | 684 | )
|
685 | 685 |
|
686 | 686 |
|
| 687 | +def _timeout_to_request_timed_out_error(f: Failure): |
| 688 | + if f.check(twisted_error.TimeoutError, twisted_error.ConnectingCancelledError): |
| 689 | + # The TCP connection has its own timeout (set by the 'connectTimeout' param |
| 690 | + # on the Agent), which raises twisted_error.TimeoutError exception. |
| 691 | + raise RequestTimedOutError("Timeout connecting to remote server") |
| 692 | + elif f.check(defer.TimeoutError, ResponseNeverReceived): |
| 693 | + # this one means that we hit our overall timeout on the request |
| 694 | + raise RequestTimedOutError("Timeout waiting for response from remote server") |
| 695 | + |
| 696 | + return f |
| 697 | + |
| 698 | + |
687 | 699 | # XXX: FIXME: This is horribly copy-pasted from matrixfederationclient.
|
688 | 700 | # The two should be factored out.
|
689 | 701 |
|
|
0 commit comments