def __init__(self, version, address): super(RyuClientBase, self).__init__() self.version = version res = urllib_parse.SplitResult('', address, '', '', '') self.host = res.hostname self.port = res.port self.url_prefix = '/' + self.version + '/'
def on_message(self, message): try: contents = json.loads(message) except ValueError: self.log.debug('Bad JSON: %r', message) self.log.error('Couldn\'t parse JSON', exc_info=True) self._write_error(status=400, msg='JSON input is required.') return if not set(contents.keys()).issuperset(self._REQUIRED_KEYS): msg = ( 'Invalid request. The body must contain the following keys: ' '{required}. Got: {got}').format(required=self._REQUIRED_KEYS, got=contents.keys()) self._write_error(status=400, msg=msg) return method = str(contents['method']).upper() query = '' if method in self._REQUIRE_XSRF_FORWARDING_METHODS: xsrf = self.get_cookie('_xsrf') if xsrf: query += '_xsrf={}'.format(xsrf) body = contents.get('body') if method in self._REQUIRE_NO_BODY_METHODS and body is not None: msg = ( 'Invalid request: Body may not be specified for method "{}".' ).format(method) self._write_error(status=400, msg=msg) return path = urlparse.urlunsplit( urlparse.SplitResult(scheme=self.request.protocol, netloc=self.request.host, path=contents['path'], query=query, fragment='')) emitter = _StreamingResponseEmitter(contents['message_id'], self.write_message) proxy_request = httpclient.HTTPRequest( url=path, method=method, headers=self.request.headers, body=contents.get('body'), ca_certs=self.ca_certs, header_callback=emitter.header_callback, streaming_callback=emitter.streaming_callback) _modify_proxy_request_test_only(proxy_request) http_client = self._get_http_client() # Since this channel represents a proxy, don't raise errors directly and # instead send them back in the response. # The response contents will normally be captured by # _StreamingResponseEmitter. However, if a programming error occurs with how # the proxy is set up, these callbacks will not be used. response = yield http_client.fetch(proxy_request, raise_error=False) if response.error and not isinstance(response.error, httpclient.HTTPError): with stack_context.ExceptionStackContext(self._log_fetch_error): # Rethrow the exception to capture the stack trace and write # an error message. response.rethrow() self._write_error( status=500, msg=('Uncaught server-side exception. Check logs for ' 'additional details.')) return emitter.done()
def on_message(self, message): try: contents = json.loads(message) except ValueError: self.log.debug('Bad JSON: %r', message) self.log.error("Couldn't parse JSON", exc_info=True) self._write_error(status=400, msg='JSON input is required.') raise gen.Return() if not set(contents.keys()).issuperset(self._REQUIRED_KEYS): msg = ( 'Invalid request. The body must contain the following keys: ' '{required}. Got: {got}').format(required=self._REQUIRED_KEYS, got=contents.keys()) self._write_error(status=400, msg=msg, message_id=contents.get('message_id')) raise gen.Return() message_id = contents['message_id'] try: yield self._attach_auth_cookies() except Exception: # pylint:disable=broad-except self.log.error("Couldn't attach auth cookies") self._on_unhandled_exception(message_id) raise gen.Return() method = str(contents['method']).upper() query = '' if method in self._REQUIRE_XSRF_FORWARDING_METHODS: xsrf = self._get_xsrf_cookie() if xsrf: query += '_xsrf={}'.format(xsrf) path = urlparse.urlunsplit( # pylint:disable=too-many-function-args urlparse.SplitResult(scheme=self.request.protocol, netloc=self.request.host, path=contents['path'], query=query, fragment='')) body = None if contents.get('body_base64'): body = base64.b64decode( contents.get('body_base64')).decode('utf-8') else: body = contents.get('body') emitter = _StreamingResponseEmitter(message_id, self.write_message) proxy_request = httpclient.HTTPRequest( url=path, method=method, headers=self.request.headers, body=body, ca_certs=self.ca_certs, header_callback=emitter.header_callback, streaming_callback=emitter.streaming_callback, allow_nonstandard_methods=True) _modify_proxy_request_test_only(proxy_request) http_client = self._get_http_client() # Since this channel represents a proxy, don't raise errors directly and # instead send them back in the response. # The response contents will normally be captured by # _StreamingResponseEmitter. However, if a programming error occurs with how # the proxy is set up, these callbacks will not be used. response = yield http_client.fetch(proxy_request, raise_error=False) if response.error and not isinstance(response.error, httpclient.HTTPError): try: response.rethrow() except Exception: # pylint:disable=broad-except # Rethrow the exception to capture the stack trace and write # an error message. self.log.exception('Uncaught error when proxying request') self._on_unhandled_exception(message_id) raise gen.Return() emitter.done()