def test_http_error(self): res = self._make_request_with_side_effect(exc.HTTPGatewayTimeout()) # verify that the exception structure is the one expected # by the python-tackerclient self.assertEqual(exc.HTTPGatewayTimeout().explanation, res.json['TackerError']['message']) self.assertEqual('HTTPGatewayTimeout', res.json['TackerError']['type']) self.assertEqual('', res.json['TackerError']['detail']) self.assertEqual(exc.HTTPGatewayTimeout.code, res.status_int)
def make_imaged_request(self, method, imaged_url, headers, body, stream): timeout = (self.config.imaged_connection_timeout_sec, self.config.imaged_read_timeout_sec) logging.debug("Connecting to host at %s", imaged_url) logging.debug("Outgoing headers to host:\n" + '\n'.join((' {}: {}'.format(k, headers[k]) for k in sorted(headers)))) try: # TODO Pool requests, keep the session somewhere? # TODO Otherwise, we can use request.prepare() imaged_session = requests.Session() imaged_req = requests.Request(method, imaged_url, headers=headers, data=body) imaged_req.body_file = body # TODO log the request to vdsm imaged_prepped = imaged_session.prepare_request(imaged_req) imaged_resp = imaged_session.send( imaged_prepped, verify=config.engine_ca_cert_file, timeout=timeout, stream=stream) except requests.Timeout: s = "Timed out connecting to host" raise exc.HTTPGatewayTimeout(s) except requests.URLRequired: s = "Invalid host URI for host" raise exc.HTTPBadRequest(s) except requests.ConnectionError as e: s = "Failed communicating with host: " + e.__doc__ logging.error(s, exc_info=True) raise exc.HTTPServiceUnavailable(s) except requests.RequestException as e: s = "Failed communicating with host: " + e.__doc__ logging.error(s, exc_info=True) raise exc.HTTPInternalServerError(s) print imaged_resp.headers # logging.debug("Incoming headers from host:\n" + # '\n'.join((' {}: {}' # .format(k, imaged_resp.headers.get(k)) # for k in sorted(imaged_resp.headers)))) if imaged_resp.status_code not in http_success_codes: # Don't read the whole body, in case something went really wrong... s = next(imaged_resp.iter_content(256, False), "(empty)") logging.error("Failed: %s", s) # TODO why isn't the exception logged somewhere? raise exc.status_map[imaged_resp.status_code]( "Failed response from host: {}".format(s)) logging.debug("Successful request to host: HTTP %d %s", imaged_resp.status_code, httplib.responses[imaged_resp.status_code]) return imaged_resp
def test_http_error(self): controller = mock.MagicMock() controller.test.side_effect = exc.HTTPGatewayTimeout() resource = webtest.TestApp(wsgi_resource.Resource(controller)) environ = {'wsgiorg.routing_args': (None, {'action': 'test'})} res = resource.get('', extra_environ=environ, expect_errors=True) self.assertEqual(res.status_int, exc.HTTPGatewayTimeout.code)
def make_imaged_request(self, method, imaged_url, headers, body, stream, connection_timeout=None, read_timeout=None): logging.debug("Connecting to host at %s", imaged_url) logging.debug("Outgoing headers to host:\n" + '\n'.join((' {}: {}'.format(k, headers[k]) for k in sorted(headers)))) try: # TODO Pool requests, keep the session somewhere? # TODO Otherwise, we can use request.prepare() imaged_session = requests.Session() imaged_req = requests.Request(method, imaged_url, headers=headers, data=body) imaged_req.body_file = body # TODO log the request to vdsm imaged_prepped = imaged_session.prepare_request(imaged_req) imaged_resp = imaged_session.send( imaged_prepped, verify=config.engine_ca_cert_file, timeout=(connection_timeout, read_timeout), stream=stream) except requests.Timeout: s = "Timed out connecting to host" raise exc.HTTPGatewayTimeout(s) except requests.URLRequired: s = "Invalid host URI for host" raise exc.HTTPBadRequest(s) except requests.ConnectionError as e: s = "Failed communicating with host: " + e.__doc__ logging.error(s, exc_info=True) raise exc.HTTPServiceUnavailable(s) except requests.RequestException as e: s = "Failed communicating with host: " + e.__doc__ logging.error(s, exc_info=True) raise exc.HTTPInternalServerError(s) logging.debug("Incoming headers from host:\n" + '\n'.join( (' {}: {}'.format(k, imaged_resp.headers.get(k)) for k in sorted(imaged_resp.headers)))) if imaged_resp.status_code not in http_success_codes: s = "Failed response from host: %d %s" % \ (imaged_resp.status_code, imaged_resp.content) raise exc.status_map[imaged_resp.status_code](s) logging.debug("Successful request to host: HTTP %d %s", imaged_resp.status_code, httplib.responses[imaged_resp.status_code]) return imaged_resp
def code2exception(code, detail): """Transforms a code + detail into a WebOb exception""" if code == 400: return exc.HTTPBadRequest(detail) if code == 401: return exc.HTTPUnauthorized(detail) if code == 402: return exc.HTTPPaymentRequired(detail) if code == 403: return exc.HTTPForbidden(detail) if code == 404: return exc.HTTPNotFound(detail) if code == 405: return exc.HTTPMethodNotAllowed(detail) if code == 406: return exc.HTTPNotAcceptable(detail) if code == 407: return exc.HTTPProxyAuthenticationRequired(detail) if code == 408: return exc.HTTPRequestTimeout(detail) if code == 409: return exc.HTTPConflict(detail) if code == 410: return exc.HTTPGone(detail) if code == 411: return exc.HTTPLengthRequired(detail) if code == 412: return exc.HTTPPreconditionFailed(detail) if code == 413: return exc.HTTPRequestEntityTooLarge(detail) if code == 414: return exc.HTTPRequestURITooLong(detail) if code == 415: return exc.HTTPUnsupportedMediaType(detail) if code == 416: return exc.HTTPRequestRangeNotSatisfiable(detail) if code == 417: return exc.HTTPExpectationFailed(detail) if code == 500: return exc.HTTPInternalServerError(detail) if code == 501: return exc.HTTPNotImplemented(detail) if code == 502: return exc.HTTPBadGateway(detail) if code == 503: return exc.HTTPServiceUnavailable(detail) if code == 504: return exc.HTTPGatewayTimeout(detail) if code == 505: return exc.HTTPVersionNotSupported(detail) raise NotImplementedError(code)
def __call__(self, environ, start_response): scheme = environ['wsgi.url_scheme'] if scheme == 'http': ConnClass = self.HTTPConnection elif scheme == 'https': ConnClass = self.HTTPSConnection else: raise ValueError("Unknown scheme: %r" % scheme) if 'SERVER_NAME' not in environ: host = environ.get('HTTP_HOST') if not host: raise ValueError( "environ contains neither SERVER_NAME nor HTTP_HOST") if ':' in host: host, port = host.split(':', 1) else: if scheme == 'http': port = '80' else: port = '443' environ['SERVER_NAME'] = host environ['SERVER_PORT'] = port kw = {} if ('webob.client.timeout' in environ and self._timeout_supported(ConnClass)): kw['timeout'] = environ['webob.client.timeout'] conn = ConnClass('%(SERVER_NAME)s:%(SERVER_PORT)s' % environ, **kw) headers = {} for key, value in environ.items(): if key.startswith('HTTP_'): key = key[5:].replace('_', '-').title() headers[key] = value path = (url_quote(environ.get('SCRIPT_NAME', '')) + url_quote(environ.get('PATH_INFO', ''))) if environ.get('QUERY_STRING'): path += '?' + environ['QUERY_STRING'] try: content_length = int(environ.get('CONTENT_LENGTH', '0')) except ValueError: content_length = 0 ## FIXME: there is no streaming of the body, and that might be useful ## in some cases if content_length: body = environ['wsgi.input'].read(content_length) else: body = '' headers['Content-Length'] = content_length if environ.get('CONTENT_TYPE'): headers['Content-Type'] = environ['CONTENT_TYPE'] if not path.startswith("/"): path = "/" + path try: conn.request(environ['REQUEST_METHOD'], path, body, headers) res = conn.getresponse() except socket.timeout: resp = exc.HTTPGatewayTimeout() return resp(environ, start_response) except (socket.error, socket.gaierror) as e: if ((isinstance(e, socket.error) and e.args[0] == -2) or (isinstance(e, socket.gaierror) and e.args[0] == 8)): # Name or service not known resp = exc.HTTPBadGateway( "Name or service not known (bad domain name: %s)" % environ['SERVER_NAME']) return resp(environ, start_response) elif e.args[0] in _e_refused: # pragma: no cover # Connection refused resp = exc.HTTPBadGateway("Connection refused") return resp(environ, start_response) raise headers_out = self.parse_headers(res.msg) status = '%s %s' % (res.status, res.reason) start_response(status, headers_out) length = res.getheader('content-length') # FIXME: This shouldn't really read in all the content at once if length is not None: body = res.read(int(length)) else: body = res.read() conn.close() return [body]
def __call__(self, environ, start_response): method = environ['REQUEST_METHOD'] if (self.allowed_methods is not None and method not in self.allowed_methods): return exc.HTTPMethodNotAllowed()(environ, start_response) if 'RAW_URI' in environ: path_info = environ['RAW_URI'] elif 'REQUEST_URI' in environ: path_info = environ['REQUEST_URI'] else: if self.strip_script_name: path_info = '' else: path_info = environ['SCRIPT_NAME'] path_info += environ['PATH_INFO'] if PY3: path_info = url_quote(path_info.encode('latin-1'), LOW_CHAR_SAFE) query_string = environ['QUERY_STRING'] if query_string: path_info += '?' + query_string for key, dest in self.header_map.items(): value = environ.get(key) if value: environ['HTTP_%s' % dest] = value host_uri = self.extract_uri(environ) uri = host_uri + path_info new_headers = {} for k, v in environ.items(): if k.startswith('HTTP_'): k = k[5:].replace('_', '-').title() new_headers[k] = v content_type = environ.get("CONTENT_TYPE") if content_type and content_type is not None: new_headers['Content-Type'] = content_type content_length = environ.get('CONTENT_LENGTH') transfer_encoding = environ.get('Transfer-Encoding', '').lower() if not content_length and transfer_encoding != 'chunked': new_headers['Transfer-Encoding'] = 'chunked' elif content_length: new_headers['Content-Length'] = content_length if new_headers.get('Content-Length', '0') == '-1': resp = exc.HTTPInternalServerError(detail=WEBOB_ERROR) return resp(environ, start_response) try: response = self.process_request(uri, method, new_headers, environ) except socket.timeout: return exc.HTTPGatewayTimeout()(environ, start_response) except (socket.error, socket.gaierror): return exc.HTTPBadGateway()(environ, start_response) except Exception as e: self.logger.exception(e) return exc.HTTPInternalServerError()(environ, start_response) status, location, headerslist, app_iter = response if location: if self.strip_script_name: prefix_path = environ['SCRIPT_NAME'] else: prefix_path = None new_location = rewrite_location(host_uri, location, prefix_path=prefix_path) headers = [] for k, v in headerslist: if k.lower() == 'location': v = new_location headers.append((k, v)) else: headers = headerslist start_response(status, headers) if method == "HEAD": return [six.b('')] return app_iter
def __call__(self, environ, start_response): scheme = environ["wsgi.url_scheme"] if scheme == "http": ConnClass = self.HTTPConnection elif scheme == "https": ConnClass = self.HTTPSConnection else: raise ValueError("Unknown scheme: %r" % scheme) if "SERVER_NAME" not in environ: host = environ.get("HTTP_HOST") if not host: raise ValueError( "environ contains neither SERVER_NAME nor HTTP_HOST") if ":" in host: host, port = host.split(":", 1) else: if scheme == "http": port = "80" else: port = "443" environ["SERVER_NAME"] = host environ["SERVER_PORT"] = port kw = {} if "webob.client.timeout" in environ and self._timeout_supported( ConnClass): kw["timeout"] = environ["webob.client.timeout"] conn = ConnClass("%(SERVER_NAME)s:%(SERVER_PORT)s" % environ, **kw) headers = {} for key, value in environ.items(): if key.startswith("HTTP_"): key = key[5:].replace("_", "-").title() headers[key] = value path = url_quote(environ.get("SCRIPT_NAME", "")) + url_quote( environ.get("PATH_INFO", "")) if environ.get("QUERY_STRING"): path += "?" + environ["QUERY_STRING"] try: content_length = int(environ.get("CONTENT_LENGTH", "0")) except ValueError: content_length = 0 # FIXME: there is no streaming of the body, and that might be useful # in some cases if content_length: body = environ["wsgi.input"].read(content_length) else: body = "" headers["Content-Length"] = content_length if environ.get("CONTENT_TYPE"): headers["Content-Type"] = environ["CONTENT_TYPE"] if not path.startswith("/"): path = "/" + path try: conn.request(environ["REQUEST_METHOD"], path, body, headers) res = conn.getresponse() except socket.timeout: resp = exc.HTTPGatewayTimeout() return resp(environ, start_response) except (OSError, socket.gaierror) as e: if (isinstance(e, socket.error) and e.args[0] == -2) or (isinstance(e, socket.gaierror) and e.args[0] == 8): # Name or service not known resp = exc.HTTPBadGateway( "Name or service not known (bad domain name: %s)" % environ["SERVER_NAME"]) return resp(environ, start_response) elif e.args[0] in _e_refused: # pragma: no cover # Connection refused resp = exc.HTTPBadGateway("Connection refused") return resp(environ, start_response) raise headers_out = self.parse_headers(res.msg) status = "%s %s" % (res.status, res.reason) start_response(status, headers_out) length = res.getheader("content-length") # FIXME: This shouldn't really read in all the content at once if length is not None: body = res.read(int(length)) else: body = res.read() conn.close() return [body]