From 4d232e21cfd479717e21687331ca4d3acce24d92 Mon Sep 17 00:00:00 2001 From: Jake Bennett Date: Tue, 29 Apr 2014 12:20:58 +0100 Subject: [PATCH 1/2] Fix handling of redirects. Previously, if a url caused a redirect, the redirected url and time would be recorded twice(or more times for more redirects) in the results, as opposed to correct info for each individual request being recorded before the subsequent redirect. --- loads/measure.py | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/loads/measure.py b/loads/measure.py index b34a65c..ec5531b 100644 --- a/loads/measure.py +++ b/loads/measure.py @@ -1,7 +1,7 @@ import datetime import urlparse -from requests.sessions import Session as _Session +from requests.sessions import Session as _Session, REDIRECT_STATI from webtest.app import TestApp as _TestApp from wsgiproxy.proxies import HostProxy as _HostProxy from wsgiproxy.requests_client import HttpClient @@ -78,16 +78,36 @@ def request(self, method, url, headers=None, **kwargs): return super(Session, self).request( method, url, headers=headers, **kwargs) + def resolve_redirects(self, resp, req, stream=False, timeout=None, + verify=True, cert=None, proxies=None): + """If there is a redirect, need to record information about the hit before + it is obliterated by the next request.""" + # Future version of requests (some time > 2.2.1) has Response.is_redirect + if ('location' in resp.headers) and resp.status_code in REDIRECT_STATI: + resp.started = self._started + resp.method = req.method + self._analyse_request(resp) + return _Session.resolve_redirects(self, resp, req, stream=stream, timeout=timeout, + verify=verify,cert=cert,proxies=proxies) + def send(self, request, **kwargs): """Do the actual request from within the session, doing some measures at the same time about the request (duration, status, etc). """ + # Recording information about a hit may or may not take place here. + # If the hit is a redirect, it will clear the following flag when + # it records, so that we know not to do it twice. + self._need_to_analyse = True # attach some information to the request object for later use. - start = datetime.datetime.utcnow() + self._started = datetime.datetime.utcnow() res = _Session.send(self, request, **kwargs) - res.started = start - res.method = request.method - self._analyse_request(res) + if hasattr(self, '_need_to_analyse'): + # Reaching this code means the url was not a redirect, and so still + # needs analysing. + res.started = self._started + res.method = request.method + self._analyse_request(res) + delattr(self, '_need_to_analyse') return res def _analyse_request(self, req): From e245fbf880400c445aa601880cd1d1384aa8e5c7 Mon Sep 17 00:00:00 2001 From: Jake Bennett Date: Tue, 29 Apr 2014 18:31:30 +0100 Subject: [PATCH 2/2] Minor changes based on feedback. Fixed bug introduced by last commit where setting allow_redirects=False caused hits to be logged twice. --- loads/measure.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/loads/measure.py b/loads/measure.py index ec5531b..163e86a 100644 --- a/loads/measure.py +++ b/loads/measure.py @@ -83,10 +83,11 @@ def resolve_redirects(self, resp, req, stream=False, timeout=None, """If there is a redirect, need to record information about the hit before it is obliterated by the next request.""" # Future version of requests (some time > 2.2.1) has Response.is_redirect - if ('location' in resp.headers) and resp.status_code in REDIRECT_STATI: + if 'location' in resp.headers and resp.status_code in REDIRECT_STATI: resp.started = self._started resp.method = req.method self._analyse_request(resp) + req._needs_analysis = False return _Session.resolve_redirects(self, resp, req, stream=stream, timeout=timeout, verify=verify,cert=cert,proxies=proxies) @@ -94,20 +95,19 @@ def send(self, request, **kwargs): """Do the actual request from within the session, doing some measures at the same time about the request (duration, status, etc). """ - # Recording information about a hit may or may not take place here. - # If the hit is a redirect, it will clear the following flag when - # it records, so that we know not to do it twice. - self._need_to_analyse = True + # If the request receives a redirect response code, collecting the + # result will be handled by resolve_redirects() before the result + # object is thrown away to perform the redirect. In that case, this + # flag will be set to false, indicating that nothing needs to be + # (or should be) recorded at the end of this method. + request._needs_analysis = True # attach some information to the request object for later use. self._started = datetime.datetime.utcnow() res = _Session.send(self, request, **kwargs) - if hasattr(self, '_need_to_analyse'): - # Reaching this code means the url was not a redirect, and so still - # needs analysing. + if request._needs_analysis == True: res.started = self._started res.method = request.method self._analyse_request(res) - delattr(self, '_need_to_analyse') return res def _analyse_request(self, req):