def _get_request_response_from_work_unit(self, work_unit): """ In some cases the work unit is a tuple with request / response instances. In other cases it is an ID, which needs to be queried from the History DB to get the request / response. :param work_unit: One of the options explained above :return: A request / response tuple """ if not isinstance(work_unit, int): request, response = work_unit else: # Before we sent requests and responses as work units, # but since we changed from Queue to CachedQueue for BaseConsumer # the database was growing really big (1GB) for storing that traffic # and I decided to migrate to using just the response.id and querying # the SQLite one extra time. history = HistoryItem() request, response = history.load_from_file(work_unit) # Create a fuzzable request based on the urllib2 request object headers_inst = Headers(request.header_items()) request = FuzzableRequest.from_parts(request.url_object, request.get_method(), request.get_data() or '', headers_inst) return request, response
def _get_request_response_from_work_unit(self, work_unit): """ In some cases the work unit is a tuple with request / response instances. In other cases it is an ID, which needs to be queried from the History DB to get the request / response. :param work_unit: One of the options explained above :return: A request / response tuple """ if not isinstance(work_unit, int): request, response = work_unit else: # Before we sent requests and responses as work units, # but since we changed from Queue to CachedQueue for BaseConsumer # the database was growing really big (1GB) for storing that traffic # and I decided to migrate to using just the response.id and querying # the SQLite one extra time. history = HistoryItem() request, response = history.load_from_file(work_unit) # Create a fuzzable request based on the urllib2 request object headers_inst = Headers(request.header_items()) request = FuzzableRequest.from_parts(request.url_object, request.get_method(), request.get_data() or '', headers_inst) return request, response
def _get_request_response_from_id_impl(self, http_response_id): """ Just reads the request and response from the files. No threading, events, caching, etc. :param http_response_id: The HTTP response ID :return: An HTTP request and response tuple """ history = HistoryItem() request, response = history.load_from_file(http_response_id) # Create a fuzzable request based on the urllib2 request object headers_inst = Headers(request.header_items()) request = FuzzableRequest.from_parts(request.url_object, request.get_method(), request.get_data() or '', headers_inst) return request, response
def to_string(self): """ :return: An xml node (as a string) representing the HTTP request / response. <http-transaction id="..."> <http-request> <status></status> <headers> <header> <field></field> <content></content> </header> </headers> <body content-encoding="base64"></body> </http-request> <http-response> <status></status> <headers> <header> <field></field> <content></content> </header> </headers> <body content-encoding="base64"></body> </http-response> </http-transaction> One of the differences this class has with the previous implementation is that the body is always encoded, no matter the content-type. This helps prevent encoding issues. """ # Get the data from the cache node = self.get_node_from_cache() if node is not None: return node # HistoryItem to get requests/responses req_history = HistoryItem() # This might raise a DBException in some cases (which I still # need to identify and fix). When an exception is raised here # the caller needs to handle it by ignoring this part of the # HTTP transaction request, response = req_history.load_from_file(self._id) data = request.get_data() or '' b64_encoded_request_body = base64.encodestring(smart_str_ignore(data)) body = response.get_body() or '' b64_encoded_response_body = base64.encodestring(smart_str_ignore(body)) context = { 'id': self._id, 'request': { 'status': request.get_request_line().strip(), 'headers': request.get_headers(), 'body': b64_encoded_request_body }, 'response': { 'status': response.get_status_line().strip(), 'headers': response.get_headers(), 'body': b64_encoded_response_body } } context = dotdict(context) template = self.get_template(self.TEMPLATE) transaction = template.render(context) self.save_node_to_cache(transaction) return transaction
def to_string(self): """ :return: An xml node (as a string) representing the HTTP request / response. <http-transaction id="..."> <http-request> <status></status> <headers> <header> <field></field> <content></content> </header> </headers> <body content-encoding="base64"></body> </http-request> <http-response> <status></status> <headers> <header> <field></field> <content></content> </header> </headers> <body content-encoding="base64"></body> </http-response> </http-transaction> One of the differences this class has with the previous implementation is that the body is always encoded, no matter the content-type. This helps prevent encoding issues. """ # Get the data from the cache node = self.get_node_from_cache() if node is not None: return node # HistoryItem to get requests/responses req_history = HistoryItem() # This might raise a DBException in some cases (which I still # need to identify and fix). When an exception is raised here # the caller needs to handle it by ignoring this part of the # HTTP transaction request, response = req_history.load_from_file(self._id) data = request.get_data() or '' b64_encoded_request_body = base64.encodestring(smart_str_ignore(data)) body = response.get_body() or '' b64_encoded_response_body = base64.encodestring(smart_str_ignore(body)) context = {'id': self._id, 'request': {'status': request.get_request_line().strip(), 'headers': request.get_headers(), 'body': b64_encoded_request_body}, 'response': {'status': response.get_status_line().strip(), 'headers': response.get_headers(), 'body': b64_encoded_response_body}} context = dotdict(context) template = self.get_template(self.TEMPLATE) transaction = template.render(context) self.save_node_to_cache(transaction) return transaction