def _generic_send_error_handler(self, req, exception, grep, original_url): if not req.error_handling: msg = u'Raising HTTP error "%s" "%s". Reason: "%s". Error' \ u' handling was disabled for this request.' om.out.debug(msg % (req.get_method(), original_url, exception)) error_str = get_exception_reason(exception) or str(exception) raise HTTPRequestException(error_str, request=req) # Log the error msg = u'Failed to HTTP "%s" "%s". Reason: "%s", going to retry.' om.out.debug(msg % (req.get_method(), original_url, exception)) # Don't make a lot of noise on URLTimeoutError which is pretty common # and properly handled by this library if not isinstance(exception, URLTimeoutError): msg = 'Traceback for this error: %s' om.out.debug(msg % traceback.format_exc()) with self._count_lock: self._log_failed_response(exception, req) should_stop_scan = self._should_stop_scan(req) if should_stop_scan: self._handle_error_count_exceeded(exception) # Then retry! req._Request__original = original_url return self._retry(req, grep, exception)
def _handle_error_count_exceeded(self, error): """ Handle the case where we exceeded MAX_ERROR_COUNT """ # Create a detailed exception message msg = ('w3af found too many consecutive errors while performing' ' HTTP requests. In most cases this means that the remote web' ' server is not reachable anymore, the network is down, or' ' a WAF is blocking our tests. The last exception message' ' was "%s" (%s.%s).') reason_msg = get_exception_reason(error) args = (error, error.__class__.__module__, error.__class__.__name__) # If I got a reason, it means that it is a known exception. if reason_msg is not None: # Stop using ExtendedUrllib instance e = ScanMustStopByKnownReasonExc(msg % args, reason=reason_msg) else: last_errors = [] last_n_responses = list(self._last_responses)[-MAX_ERROR_COUNT:] for response_meta in last_n_responses: last_errors.append(response_meta.message) e = ScanMustStopByUnknownReasonExc(msg % args, errs=last_errors) self._stop_exception = e # pylint: disable=E0702 raise self._stop_exception
def _log_failed_response(self, error, request): """ Add the failed response to the self._last_responses log, and if we got a lot of failures raise a "ScanMustStopException" subtype. :param error: Exception object. """ reason = get_exception_reason(error) reason = reason or str(error) self._last_responses.append( ResponseMeta(False, reason, host=request.get_host())) self._log_error_rate()
def _log_failed_response(self, error, request): """ Add the failed response to the self._last_responses log, and if we got a lot of failures raise a "ScanMustStopException" subtype. :param error: Exception object. """ reason = get_exception_reason(error) reason = reason or str(error) self._last_responses.append(ResponseMeta(False, reason, host=request.get_host())) self._log_error_rate()
def _retry(self, req, grep, url_error): """ Try to send the request again while doing some error handling. """ req.retries_left -= 1 if req.retries_left > 0: msg = 'Re-sending request "%s" after initial exception: "%s"' om.out.debug(msg % (req, url_error)) return self.send(req, grep=grep) else: # Please note that I'm raising HTTPRequestException and not a # ScanMustStopException (or subclasses) since I don't want the # scan to stop because of a single HTTP request failing. # # Actually we get here if one request fails three times to be sent # but that might be because of the http request itself and not a # fault of the framework/server/network. error_str = get_exception_reason(url_error) or str(url_error) raise HTTPRequestException(error_str, request=req)