def _execute(self, transforms, *args, **kwargs): with stack_context.ExceptionStackContext( self._handle_websocket_exception): # Websocket only supports GET method if self.request.method != 'GET': self.stream.write( tornado.escape.utf8( "HTTP/1.1 405 Method Not Allowed\r\n\r\n")) self.stream.close() return # Upgrade header should be present and should be equal to WebSocket if self.request.headers.get("Upgrade", "").lower() != 'websocket': self.stream.write( tornado.escape.utf8( "HTTP/1.1 400 Bad Request\r\n\r\n" "Can \"Upgrade\" only to \"WebSocket\".")) self.stream.close() return # Connection header should be upgrade. Some proxy servers/load balancers # might mess with it. if self.request.headers.get("Connection", "").lower().find('upgrade') == -1: self.stream.write( tornado.escape.utf8("HTTP/1.1 400 Bad Request\r\n\r\n" "\"Connection\" must be \"Upgrade\".")) self.stream.close() return super(TornadioWebSocketHandler, self)._execute(transforms, *args, **kwargs)
def wrapper(self, *args, **kwargs): if self.application._wsgi: raise Exception("@asynchronous is not supported for WSGI apps") self._auto_finish = False with stack_context.ExceptionStackContext( self._stack_context_handle_exception): return method(self, *args, **kwargs)
def Task(func, *args, **kwargs): """Runs a single asynchronous operation. Takes a function (and optional additional arguments) and runs it with those arguments plus a ``callback`` keyword argument. The argument passed to the callback is returned as the result of the yield expression. A `Task` is equivalent to a `Callback`/`Wait` pair (with a unique key generated automatically):: result = yield gen.Task(func, args) func(args, callback=(yield gen.Callback(key))) result = yield gen.Wait(key) .. versionchanged:: 3.3 ``gen.Task`` is now a function that returns a `.Future`, instead of a subclass of `YieldPoint`. It still behaves the same way when yielded. """ future = Future() def handle_exception(typ, value, tb): if future.done(): return False future.set_exc_info((typ, value, tb)) return True def set_result(result): if future.done(): return future.set_result(result) with stack_context.ExceptionStackContext(handle_exception): func(*args, callback=_argument_adapter(set_result), **kwargs) return future
def Task(func, *args, **kwargs): """Adapts a callback-based asynchronous function for use in coroutines. Takes a function (and optional additional arguments) and runs it with those arguments plus a ``callback`` keyword argument. The argument passed to the callback is returned as the result of the yield expression. .. versionchanged:: 4.0 ``gen.Task`` is now a function that returns a `.Future`, instead of a subclass of `YieldPoint`. It still behaves the same way when yielded. """ future = _create_future() def handle_exception(typ, value, tb): if future.done(): return False future_set_exc_info(future, (typ, value, tb)) return True def set_result(result): if future.done(): return future_set_result_unless_cancelled(future, result) with stack_context.ExceptionStackContext(handle_exception): func(*args, callback=_argument_adapter(set_result), **kwargs) return future
def __init__( self, io_loop, context, request, stream_id, release_callback=None, final_callback=None): self.io_loop = io_loop self.start_time = self.io_loop.time() self.context = context self.release_callback = release_callback self.final_callback = final_callback self.chunks = [] self.headers = None self.code = None self.reason = None self._timeout = None self._pushed_streams = {} self._pushed_responses = {} self._stream_ended = False self._finalized = False self._decompressor = None self._pending_body = None self._sent = False self.stream_id = stream_id self.request = request self.context.set_stream_delegate(self.stream_id, self) if request.request_timeout: with stack_context.ExceptionStackContext(self.handle_exception): self._timeout = self.io_loop.add_timeout( self.start_time + request.request_timeout, self._on_timeout)
def __wrapper__(*args, **kwargs): _stack_context_handle_exception_partial = partial( _stack_context_handle_exception, handler=args[0]) yield run_with_stack_context( stack_context.ExceptionStackContext( _stack_context_handle_exception_partial, delay_warning=True), lambda: method(*args, **kwargs))
def __init__(self, io_loop, client, request, release_callback, final_callback, max_buffer_size, tcp_client, max_header_size, max_body_size): self.start_time = io_loop.time() self.io_loop = io_loop self.client = client self.request = request self.release_callback = release_callback self.final_callback = final_callback self.max_buffer_size = max_buffer_size self.tcp_client = tcp_client self.max_header_size = max_header_size self.max_body_size = max_body_size self.code = None self.headers = None self.chunks = [] self._decompressor = None # Timeout handle returned by IOLoop.add_timeout self._timeout = None self._sockaddr = None with stack_context.ExceptionStackContext(self._handle_exception): self.parsed = urlparse.urlsplit(_unicode(self.request.url)) if self.parsed.scheme not in ("http", "https"): raise ValueError("Unsupported url scheme: %s" % self.request.url) # urlsplit results have hostname and port results, but they # didn't support ipv6 literals until python 2.7. netloc = self.parsed.netloc if "@" in netloc: userpass, _, netloc = netloc.rpartition("@") host, port = httputil.split_host_and_port(netloc) if port is None: port = 443 if self.parsed.scheme == "https" else 80 if re.match(r'^\[.*\]$', host): # raw ipv6 addresses in urls are enclosed in brackets host = host[1:-1] self.parsed_hostname = host # save final host for _on_connect if request.allow_ipv6 is False: af = socket.AF_INET else: af = socket.AF_UNSPEC ssl_options = self._get_ssl_options(self.parsed.scheme) timeout = min(self.request.connect_timeout, self.request.request_timeout) if timeout: self._timeout = self.io_loop.add_timeout( self.start_time + timeout, stack_context.wrap( functools.partial(self._on_timeout, "while connecting"))) self.tcp_client.connect(host, port, af=af, ssl_options=ssl_options, max_buffer_size=self.max_buffer_size, callback=self._on_connect)
def __init__(self, callback, barrier_type, on_exception=None): callback = stack_context.wrap(callback) on_exception = stack_context.wrap(on_exception) # Parent frame is derived class __init__, so get grandparent frame. frame = sys._getframe().f_back.f_back self._barrier = _Barrier(callback, on_exception, barrier_type, frame) self._stack_context = stack_context.ExceptionStackContext( self._barrier.ReportException)
def handle_yield(self, yielded): # Lists containing YieldPoints require stack contexts; # other lists are handled in convert_yielded. if _contains_yieldpoint(yielded): yielded = multi(yielded) if isinstance(yielded, YieldPoint): # YieldPoints are too closely coupled to the Runner to go # through the generic convert_yielded mechanism. self.future = Future() def start_yield_point(): try: yielded.start(self) if yielded.is_ready(): future_set_result_unless_cancelled( self.future, yielded.get_result()) else: self.yield_point = yielded except Exception: self.future = Future() future_set_exc_info(self.future, sys.exc_info()) if self.stack_context_deactivate is None: # Start a stack context if this is the first # YieldPoint we've seen. with stack_context.ExceptionStackContext( self.handle_exception) as deactivate: self.stack_context_deactivate = deactivate def cb(): start_yield_point() self.run() self.io_loop.add_callback(cb) return False else: start_yield_point() else: try: self.future = convert_yielded(yielded) except BadYieldError: self.future = Future() future_set_exc_info(self.future, sys.exc_info()) if self.future is moment: self.io_loop.add_callback(self.run) return False elif not self.future.done(): def inner(f): # Break a reference cycle to speed GC. f = None # noqa self.run() self.io_loop.add_future(self.future, inner) return False return True
def testWithStackContext2(self): """Ensure Retry doesn't interfere with asynchronous function that throws immediately.""" try: with stack_context.ExceptionStackContext(self._OnError): retry.CallWithRetryAsync(retry.RetryPolicy(), self._AsyncFuncRaisesError, callback=self._OnCompleted) self.assert_(False, 'Expected exception to be raised') except: self.wait()
def test_stack_context(self): # See http://tornadoweb.org/en/stable/stack_context.html # MotorPool.get_socket can block waiting for a callback in another # context to return a socket. We verify MotorPool's stack-context # handling by testing that exceptions raised in get_socket's # continuation are caught in get_socket's stack context, not # return_socket's. loop = self.io_loop history = [] cx = self.motor_client(max_pool_size=1) # Open a socket yield cx.motor_test.test_collection.find_one() pool = cx._get_primary_pool() self.assertEqual(1, len(pool.sockets)) sock_info = pool.get_socket() main_gr = greenlet.getcurrent() def catch_get_sock_exc(exc_type, exc_value, exc_traceback): history.extend(['get_sock_exc', exc_value]) return True # Don't propagate def catch_return_sock_exc(exc_type, exc_value, exc_traceback): history.extend(['return_sock_exc', exc_value]) return True # Don't propagate def get_socket(): # Blocks until socket is available, since max_pool_size is 1. pool.get_socket() loop.add_callback(raise_callback) my_assert = AssertionError('foo') def raise_callback(): history.append('raise') raise my_assert def return_socket(): with stack_context.ExceptionStackContext(catch_return_sock_exc): pool.maybe_return_socket(sock_info) main_gr.switch() with stack_context.ExceptionStackContext(catch_get_sock_exc): loop.add_callback(greenlet.greenlet(get_socket).switch) greenlet.greenlet(return_socket).switch() yield self.pause(0.1) # 'return_sock_exc' was *not* added to history, because stack context # wasn't leaked from return_socket to get_socket. self.assertEqual(['raise', 'get_sock_exc', my_assert], history) cx.close()
def __init__(self, io_loop, client, request, release_callback, final_callback, max_buffer_size): self.start_time = io_loop.time() self.io_loop = io_loop self.client = client self.request = request self.release_callback = release_callback self.final_callback = final_callback self.max_buffer_size = max_buffer_size self.code = None self.headers = None self.chunks = None self._decompressor = None # Timeout handle returned by IOLoop.add_timeout self._timeout = None with stack_context.ExceptionStackContext(self._handle_exception): self.parsed = urlparse.urlsplit(_unicode(self.request.url)) if ssl is None and self.parsed.scheme == "https": raise ValueError("HTTPS requires either python2.6+ or " "curl_httpclient") if self.parsed.scheme not in ("http", "https"): raise ValueError("Unsupported url scheme: %s" % self.request.url) # urlsplit results have hostname and port results, but they # didn't support ipv6 literals until python 2.7. netloc = self.parsed.netloc if "@" in netloc: userpass, _, netloc = netloc.rpartition("@") match = re.match(r'^(.+):(\d+)$', netloc) if match: host = match.group(1) port = int(match.group(2)) else: host = netloc port = 443 if self.parsed.scheme == "https" else 80 if re.match(r'^\[.*\]$', host): # raw ipv6 addresses in urls are enclosed in brackets host = host[1:-1] self.parsed_hostname = host # save final host for _on_connect if self.client.hostname_mapping is not None: host = self.client.hostname_mapping.get(host, host) if request.allow_ipv6: af = socket.AF_UNSPEC else: # We only try the first IP we get from getaddrinfo, # so restrict to ipv4 by default. af = socket.AF_INET self.client.resolver.getaddrinfo(host, port, af, socket.SOCK_STREAM, 0, 0, callback=self._on_resolve)
def on_connect(self, io_stream): log.debug('IOStream opened %s', type(io_stream)) if self.timed_out: log.debug('Connection timeout before socket connected!') io_stream.close() return if self.secure: if io_stream.socket.selected_alpn_protocol() not in AlPN_PROTOCOLS: log.error( 'Negotiated protocols mismatch, got %s, expected one of %s', io_stream.socket.selected_alpn_protocol(), AlPN_PROTOCOLS ) raise ConnectionError('Negotiated protocols mismatch') self._is_connected = True # remove the connection timeout self.io_loop.remove_timeout(self._connect_timeout_t) self._connect_timeout_t = None self.io_stream = io_stream self.io_stream.set_nodelay(True) # set the close callback self.io_stream.set_close_callback(self.on_close) # initialize the connection self.h2conn = h2.connection.H2Connection( h2.config.H2Configuration(client_side=True) ) # initiate the h2 connection self.h2conn.initiate_connection() # disable server push self.h2conn.update_settings({ h2.settings.SettingCodes.ENABLE_PUSH: 0, h2.settings.SettingCodes.MAX_CONCURRENT_STREAMS: self.max_concurrent_streams, h2.settings.SettingCodes.INITIAL_WINDOW_SIZE: self.initial_window_size }) # set the stream reading callback with stack_context.ExceptionStackContext( functools.partial(self.on_error, 'during read') ): self.io_stream.read_bytes( num_bytes=65535, streaming_callback=self.data_received, callback=self.data_received ) self.flush()
def process_events(self, events): """ Processes events received on the HTTP/2 connection and dispatches them to their corresponding HTTPStreams. """ recv_streams = dict() for event in events: log.debug(['PROCESSING EVENT', event]) stream_id = getattr(event, 'stream_id', None) if type(event) in self.event_handlers: for ev_handler in self.event_handlers[type(event)]: ev_handler(event) if isinstance(event, h2.events.DataReceived): recv_streams[stream_id] = (recv_streams.get(stream_id, 0) + event.flow_controlled_length) elif isinstance(event, h2.events.WindowUpdated): if stream_id == 0: self.flow_control_window.produce(event.delta) log.debug( 'INCREMENTED CONNECTION WINDOW BY %d, NOW AT %d', event.delta, self.flow_control_window.value ) elif isinstance(event, h2.events.RemoteSettingsChanged): self.process_settings(event) if stream_id and stream_id in self._ongoing_streams: stream = self._ongoing_streams[stream_id] with stack_context.ExceptionStackContext( stream.handle_exception ): stream.handle_event(event) recv_connection = 0 for stream_id, num_bytes in six.iteritems(recv_streams): if not num_bytes or stream_id not in self._ongoing_streams: continue log.debug( 'Incrementing flow control window for stream %d with %d', stream_id, num_bytes ) self.h2conn.increment_flow_control_window(num_bytes, stream_id) recv_connection += num_bytes if recv_connection: log.debug( 'Incrementing window flow control with %d', recv_connection ) self.h2conn.increment_flow_control_window(recv_connection) # flush data that has been generated after processing these events self.flush()
def send(self, subject='Uber Now', body='Its time to book Uber'): with stack_context.ExceptionStackContext(self.error_handler): send_mail(str(subject), str(body), self.fro, [self.to], callback=self.callback, connection=EmailBackend(self.host, self.port, self.username, self.password, True))
def testWithStackContext3(self): """Ensure Retry doesn't interfere with asynchronous callback that throws.""" try: with stack_context.ExceptionStackContext(self._OnError): retry.CallWithRetryAsync(retry.RetryPolicy(check_exception=lambda typ, val, tb: True), self._AsyncFunc, callback=self._OnCompletedRaisesError) self.wait() self.assert_(False, 'Expected exception to be raised') except Exception as e: self.assert_('_OnCompletedRaisesError' in e.message, e)
def resolve(self): self.proxy_host = getattr(self.request, 'proxy_host', None) self.proxy_port = getattr(self.request, 'proxy_port', 8080) if self.proxy_host: host = self.proxy_host port = self.proxy_port self.is_support_keepalive = False with stack_context.ExceptionStackContext(self._handle_exception): self.parsed = urlparse.urlsplit(_unicode(self.request.url)) if self.parsed.scheme not in ("http", "https"): raise ValueError("Unsupported url scheme: %s" % self.request.url) # urlsplit results have hostname and port results, but they # didn't support ipv6 literals until python 2.7. netloc = self.parsed.netloc if "@" in netloc: userpass, _, netloc = netloc.rpartition("@") match = re.match(r'^(.+):(\d+)$', netloc) if match: host = match.group(1) port = int(match.group(2)) else: host = netloc port = 443 if self.parsed.scheme == "https" else 80 if re.match(r'^\[.*\]$', host): # raw ipv6 addresses in urls are enclosed in brackets host = host[1:-1] self.parsed_hostname = host # save final host for _on_connect if self.request.allow_ipv6: af = socket.AF_UNSPEC else: # We only try the first IP we get from getaddrinfo, # so restrict to ipv4 by default. af = socket.AF_INET self.update_timeout() if self.is_connected(): self.logger.info('is connecting ....') self._on_connect() else: if not self.proxy_host: self.resolver.resolve(host, port, af, callback=self._on_resolve) else: self.resolver.resolve(self.proxy_host, self.proxy_port, af, callback=self._on_resolve)
def read_until_cancelled(*args, **kwargs): if cancelled(): return with stack_context.ExceptionStackContext( partial(self.on_error, 'during read', cancelled)): self.io_stream.read_bytes( num_bytes=65535, streaming_callback=partial( self.receive_data_until_cancelled, cancelled), callback=read_until_cancelled)
def wrapper(self, *args, **kwargs): self._auto_finish = False self.token = yield stack_context.run_with_stack_context( stack_context.ExceptionStackContext( self._stack_context_handle_exception), self.validate_token) if not self.token: raise tornado.web.HTTPError(403) with stack_context.ExceptionStackContext( self._stack_context_handle_exception): result = method(self, *args, **kwargs) if isinstance(result, Future): def future_complete(f): f.result() if not self._finished: self.finish() IOLoop.current().add_future(result, future_complete)
def _execute(self, transforms, *args, **kwargs): self.open_args = args self.open_kwargs = kwargs # Websocket only supports GET method with stack_context.ExceptionStackContext( self._handle_websocket_exception): # Websocket only supports GET method if self.request.method != 'GET': self.stream.write( tornado.escape.utf8( "HTTP/1.1 405 Method Not Allowed\r\n\r\n")) self.stream.close() return # Upgrade header should be present and should be equal to WebSocket if self.request.headers.get("Upgrade", "").lower() != 'websocket': self.stream.write( tornado.escape.utf8( "HTTP/1.1 400 Bad Request\r\n\r\n" "Can \"Upgrade\" only to \"WebSocket\".")) self.stream.close() return # Connection header should be upgrade. Some proxy servers/load balancers # might mess with it. headers = self.request.headers connection = map(lambda s: s.strip().lower(), headers.get("Connection", "").split(",")) if 'upgrade' not in connection: self.stream.write( tornado.escape.utf8("HTTP/1.1 400 Bad Request\r\n\r\n" "\"Connection\" must be \"Upgrade\".")) self.stream.close() return #self.stream.socket.setsockopt(socket.SOL_TCP, socket.TCP_NODELAY, 1) # Handle proper protocol version if self.request.headers.get("Sec-WebSocket-Version") in ("7", "8", "13"): self.ws_connection = WebSocketProtocol8(self) self.ws_connection.accept_connection() elif self.request.headers.get("Sec-WebSocket-Version"): self.stream.write( tornado.escape.utf8("HTTP/1.1 426 Upgrade Required\r\n" "Sec-WebSocket-Version: 8\r\n\r\n")) self.stream.close() else: self.ws_connection = websocket.WebSocketProtocol76(self) self.ws_connection.accept_connection()
def handle_yield(self, yielded): # Lists containing YieldPoints require stack contexts; # other lists are handled via multi_future in convert_yielded. if (isinstance(yielded, list) and any(isinstance(f, YieldPoint) for f in yielded)): yielded = Multi(yielded) elif (isinstance(yielded, dict) and any(isinstance(f, YieldPoint) for f in yielded.values())): yielded = Multi(yielded) if isinstance(yielded, YieldPoint): # YieldPoints are too closely coupled to the Runner to go # through the generic convert_yielded mechanism. self.future = TracebackFuture() def start_yield_point(): try: yielded.start(self) if yielded.is_ready(): self.future.set_result( yielded.get_result()) else: self.yield_point = yielded except Exception: self.future = TracebackFuture() self.future.set_exc_info(sys.exc_info()) if self.stack_context_deactivate is None: # Start a stack context if this is the first # YieldPoint we've seen. with stack_context.ExceptionStackContext( self.handle_exception) as deactivate: self.stack_context_deactivate = deactivate def cb(): start_yield_point() self.run() self.io_loop.add_callback(cb) return False else: start_yield_point() else: try: self.future = convert_yielded(yielded) except BadYieldError: self.future = TracebackFuture() self.future.set_exc_info(sys.exc_info()) if not self.future.done() or self.future is moment: self.io_loop.add_future( self.future, lambda f: self.run()) return False return True
def make_connection(self, ready_callback, close_callback): if self.connect_timeout: timed_out = [False] start_time = time.time() def _on_timeout(): timed_out[0] = True close_callback(io_stream=None, reason=HTTP2ConnectionTimeout(time.time() - start_time)) def _on_connect(io_stream): if timed_out[0]: io_stream.close() return self.io_loop.remove_timeout(timeout_handle) self._on_connect(io_stream, ready_callback, close_callback) timeout_handle = self.io_loop.add_timeout( start_time + self.connect_timeout, _on_timeout) else: _on_connect = functools.partial( self._on_connect, ready_callback=ready_callback, close_callback=close_callback, ) logger.info('Establishing HTTP/2 connection to %s:%s...', self.host, self.port) with stack_context.ExceptionStackContext( functools.partial(self._handle_exception, close_callback)): addr_info = socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, 0) af, sock_type, proto, canon_name, sockaddr = addr_info[0] if self.secure: io_stream = _SSLIOStream(socket.socket(af, sock_type, proto), hostname=self.host, io_loop=self.io_loop, ssl_options=self.ssl_options, max_buffer_size=self.max_buffer_size) else: io_stream = iostream.IOStream( socket.socket(af, sock_type, proto), io_loop=self.io_loop, max_buffer_size=self.max_buffer_size) io_stream.connect(sockaddr, functools.partial(_on_connect, io_stream))
def handle_yield(self, yielded): # 返回True已经完成,False表示Future未完成,添加到ioloop中 # Lists containing YieldPoints require stack contexts; # other lists are handled in convert_yielded. # 处理 yield list or dict 情况 if _contains_yieldpoint(yielded): yielded = multi(yielded) if isinstance(yielded, YieldPoint): # YieldPoints are too closely coupled to the Runner to go # through the generic convert_yielded mechanism. self.future = TracebackFuture() def start_yield_point(): try: yielded.start(self) if yielded.is_ready(): self.future.set_result(yielded.get_result()) else: self.yield_point = yielded except Exception: self.future = TracebackFuture() self.future.set_exc_info(sys.exc_info()) if self.stack_context_deactivate is None: # Start a stack context if this is the first # YieldPoint we've seen. with stack_context.ExceptionStackContext( self.handle_exception) as deactivate: self.stack_context_deactivate = deactivate def cb(): start_yield_point() self.run() self.io_loop.add_callback(cb) return False else: start_yield_point() else: # Future情况,为r = yield fetch()之类返回的Future try: self.future = convert_yielded(yielded) except BadYieldError: self.future = TracebackFuture() self.future.set_exc_info(sys.exc_info()) if not self.future.done() or self.future is moment: self.io_loop.add_future(self.future, lambda f: self.run()) return False return True
def handle_yield(self, yielded): if isinstance(yielded, list): if all(is_future(f) for f in yielded): yielded = multi_future(yielded) else: yielded = Multi(yielded) elif isinstance(yielded, dict): if all(is_future(f) for f in yielded.values()): yielded = multi_future(yielded) else: yielded = Multi(yielded) if isinstance(yielded, YieldPoint): self.future = TracebackFuture() def start_yield_point(): try: yielded.start(self) if yielded.is_ready(): self.future.set_result(yielded.get_result()) else: self.yield_point = yielded except Exception: self.future = TracebackFuture() self.future.set_exc_info(sys.exc_info()) if self.stack_context_deactivate is None: # Start a stack context if this is the first # YieldPoint we've seen. with stack_context.ExceptionStackContext( self.handle_exception) as deactivate: self.stack_context_deactivate = deactivate def cb(): start_yield_point() self.run() self.io_loop.add_callback(cb) return False else: start_yield_point() elif is_future(yielded): self.future = yielded if not self.future.done() or self.future is moment: self.io_loop.add_future(self.future, lambda f: self.run()) return False else: self.future = TracebackFuture() self.future.set_exception( BadYieldError("yielded unknown object %r" % (yielded, ))) return True
def handle_request(self, request, callback_clear_active, callback): """ Create an HTTP2Stream object for the current request. :param request: client request :type request: HTTPRequest :param callback_clear_active: function executed when the request finishes, removes the current stream from the list of active streams. :param callback: function executed when the request finishes """ stream = self.stream_cls(self.connection, request, callback_clear_active, callback, self.io_loop) with stack_context.ExceptionStackContext(stream.handle_exception): stream.begin_request()
def __init__(self, host, port, io_loop): self.io_loop = io_loop self.resolver = Resolver() self.stream = None self.queue = deque() self._callbacks = {} self._connected = False self.read_state = self.READ_HEAD self.prev_response = None self.prof = {} with stack_context.ExceptionStackContext(self._handle_exception): self.resolver.resolve(host, port, socket.AF_INET, callback=self._on_resolve)
def __init__(self, host, port, io_loop, key): self.io_loop = io_loop self.resolver = Resolver() self._callbacks = {} self._connected = False self.queue = deque() self.key = key self.stream = None self.pepv_act_resp = None self.prof = {} with stack_context.ExceptionStackContext(self._handle_exception): self.resolver.resolve(host, port, socket.AF_INET, callback=self._on_resolve)
def wrapper(self, *args, **kwargs): self._auto_finish = False with stack_context.ExceptionStackContext( self._stack_context_handle_exception): result = method(self, *args, **kwargs) if is_future(result): def future_complete(f): f.result() if not self._finished: self.finish() IOLoop.current().add_future(result, future_complete) return None return result
def _process_events(self, events): stream_inbounds = collections.defaultdict(int) for event in events: if isinstance(event, h2.events.DataReceived): stream_inbounds[ event.stream_id] += event.flow_controlled_length if isinstance(event, h2.events.PushedStreamReceived): stream_id = event.parent_stream_id else: stream_id = getattr(event, 'stream_id', None) if stream_id is not None and stream_id != 0: if stream_id in self.stream_delegates: stream_delegate = self.stream_delegates[stream_id] with stack_context.ExceptionStackContext( stream_delegate.handle_exception): stream_delegate.handle_event(event) else: # FIXME: our nginx server will simply reset stream, # without increase the window size which consumed by # queued data frame which was belongs to the stream we're resetting # self.reset_stream(stream_id) if stream_id in self.reset_stream_ids: if isinstance(event, h2.events.StreamEnded): self.reset_stream_ids.remove(stream_id) else: logger.warning('Unexpected stream: %s, event: %r', stream_id, event) continue event_type = type(event) if event_type in self.event_handlers: try: self.event_handlers[event_type](event) except Exception as err: logger.exception('Exception while handling event: %r', err) continue logger.debug('ignored event: %r, %r', event, event.__dict__) for stream_id, stream_inbound in stream_inbounds.items(): self.h2_conn.acknowledge_received_data(stream_inbound, stream_id)
def send(self, stream=False, timeout=None, verify=True, cert=None, proxies=None): request = self.request connect_timeout, self.read_timeout = parse_timeout(timeout) self.stream_body = stream # set connect timeout with stack_context.ExceptionStackContext(self._handle_exception): if connect_timeout: self._timeout = self.io_loop.call_later( connect_timeout, stack_context.wrap( functools.partial(self._on_timeout, 'while connecting'))) # set proxy related info proxy = select_proxy(request.url, proxies) self.headers = request.headers.copy() if proxy: proxy = prepend_scheme_if_needed(proxy, 'http') parsed = urlparse(proxy) scheme, host, port = parsed.scheme, proxy, parsed.port port = port or (443 if scheme == 'https' else 80) self.start_line = RequestStartLine(request.method, request.url, '') self.headers.update(get_proxy_headers(proxy)) else: host, port = None, None self.start_line = request.start_line self.tcp_client.connect(request.host, request.port, af=request.af, ssl_options=self._get_ssl_options( request, verify, cert), max_buffer_size=self.max_buffer_size, source_ip=host, source_port=port, callback=self._on_connect)