diff --git a/requests/adapters.py b/requests/adapters.py index c350ae44..d4f5d5b4 100644 --- a/requests/adapters.py +++ b/requests/adapters.py @@ -9,6 +9,7 @@ and maintain connections. """ import socket +import datetime from .models import Response from .packages.urllib3.poolmanager import PoolManager, ProxyManager @@ -155,6 +156,7 @@ class HTTPAdapter(BaseAdapter): url = self.request_url(request, proxies) chunked = not (request.body is None or 'Content-Length' in request.headers) + start = datetime.datetime.utcnow() try: if not chunked: @@ -198,6 +200,7 @@ class HTTPAdapter(BaseAdapter): preload_content=False, decode_content=False ) + finish = datetime.datetime.utcnow() except socket.error as sockerr: raise ConnectionError(sockerr) @@ -214,6 +217,7 @@ class HTTPAdapter(BaseAdapter): raise Timeout('Request timed out.') r = self.build_response(request, resp) + r.elapsed = finish - start if not stream: r.content diff --git a/requests/models.py b/requests/models.py index d86b80ae..a9e8c5ba 100644 --- a/requests/models.py +++ b/requests/models.py @@ -9,6 +9,7 @@ This module contains the primary objects that power Requests. import collections import logging +import datetime from io import BytesIO from .hooks import default_hooks @@ -471,6 +472,10 @@ class Response(object): #: A CookieJar of Cookies the server sent back. self.cookies = cookiejar_from_dict({}) + #: The amount of time elapsed between sending the request + #: and the arrival of the response (as a timedelta) + self.elapsed = datetime.timedelta(0) + def __repr__(self): return '' % (self.status_code) diff --git a/test_requests.py b/test_requests.py index 6a4409b1..d5409aa7 100644 --- a/test_requests.py +++ b/test_requests.py @@ -323,5 +323,10 @@ class RequestsTestCase(unittest.TestCase): self.assertEqual(cookie.domain, domain) self.assertEqual(cookie._rest['HttpOnly'], rest['HttpOnly']) + def test_time_elapsed_blank(self): + r = requests.get(httpbin('get')) + self.assertTrue(r.elapsed.total_seconds() > 0.0) + + if __name__ == '__main__': unittest.main()