Exemple #1
0
    def read_stream_body(self, delegate, chunk_size=1, stream_callback=None):
        _delegate, delegate = self._parse_delegate(delegate)
        remain_content = False
        need_delegate_close = True

        if not _delegate.skip_body:
            try:
                body_future = self._read_stream_body(chunk_size, delegate)
                if body_future is not None:
                    remain_content = yield body_future
                need_delegate_close = False

                if not remain_content:
                    self._read_finished = True
                    if (not self._finish_future.done()
                            and self.stream is not None
                            and not self.stream.closed()):
                        self.stream.set_close_callback(
                            self._on_connection_close)
                        yield self._finish_future
                    if self._disconnect_on_finish:
                        self.close()
            except HTTPInputError as e:
                gen_log.info("Malformed HTTP message from %s: %s",
                             self.context, e)
                self.close()
                remain_content = False
            finally:
                if need_delegate_close:
                    with _ExceptionLoggingContext(app_log):
                        delegate.on_connection_close(self.stream.error)
                if not remain_content:
                    self._clear_callbacks()
        raise gen.Return(remain_content)
    def request_received(self, event, delegate, data):
        self.event = event
        self.stream_id = event.stream_id
        log.debug("_request_received: {}".format(self.stream_id))
        if event.headers:
            with _ExceptionLoggingContext(app_log):
                hd = {k: v for k, v in event.headers}
                start_line = httputil.RequestStartLine(
                    method=hd[':method'], path=hd[':path'],
                    version='HTTP/2.0')
                header_future = delegate.headers_received(
                    start_line,
                    httputil.HTTPHeaders(hd)
                )
                if header_future is not None:
                    yield header_future

        delegate.data_received(data)
        with _ExceptionLoggingContext(app_log):
            delegate.finish()
        raise gen.Return(True)
Exemple #3
0
    def read_headers(self, delegate):
        try:
            _delegate, delegate = self._parse_delegate(delegate)
            header_future = self.stream.read_until_regex(
                b"\r?\n\r?\n", max_bytes=self.params.max_header_size)
            header_data = yield header_future
            start_line, headers = self._parse_headers(header_data)

            start_line = parse_response_start_line(start_line)
            self._response_start_line = start_line

            self._disconnect_on_finish = not self._can_keep_alive(
                start_line, headers)

            with _ExceptionLoggingContext(app_log):
                header_future = delegate.headers_received(start_line, headers)
                if header_future is not None:
                    yield header_future
            if self.stream is None:
                # We've been detached.
                raise gen.Return(False)

            # determine body skip
            #TODO: 100 <= code < 200
            if (self._request_start_line is not None
                    and self._request_start_line.method == 'HEAD'):
                _delegate.skip_body = True
            code = start_line.code
            if code == 304:
                # 304 responses may include the content-length header
                # but do not actually have a body.
                # http://tools.ietf.org/html/rfc7230#section-3.3
                _delegate.skip_body = True
            if code >= 100 and code < 200:
                # 1xx responses should never indicate the presence of
                # a body.
                if ('Content-Length' in headers
                        or 'Transfer-Encoding' in headers):
                    raise HTTPInputError("Response code %d cannot have body" %
                                         code)
                # TODO: client delegates will get headers_received twice
                # in the case of a 100-continue.  Document or change?
                yield self.read_headers(delegate)
        except HTTPInputError as e:
            gen_log.info("Malformed HTTP message from %s: %s", self.context, e)
            self.close()

            self._clear_callbacks()

            raise gen.Return(False)
        finally:
            header_future = None
        raise gen.Return(True)
Exemple #4
0
    def read_body(self, delegate):
        _delegate, delegate = self._parse_delegate(delegate)
        need_delegate_close = True

        if not _delegate.skip_body:
            try:
                body_future = self._read_body(_delegate.code,
                                              _delegate.headers, delegate)
                if body_future is not None:
                    if self._body_timeout is None:
                        yield body_future
                    else:
                        try:
                            yield gen.with_timeout(
                                self.stream.io_loop.time() +
                                self._body_timeout,
                                body_future,
                                quiet_exceptions=StreamClosedError)
                        except gen.TimeoutError:
                            gen_log.info("Timeout reading body from %s",
                                         self.context)
                            self.stream.close()
                            raise gen.Return(False)

                self._read_finished = True
                need_delegate_close = False

                # If we're waiting for the application to produce an asynchronous
                # response, and we're not detached, register a close callback
                # on the stream (we didn't need one while we were reading)
                if (not self._finish_future.done() and self.stream is not None
                        and not self.stream.closed()):
                    self.stream.set_close_callback(self._on_connection_close)
                    yield self._finish_future
                if self._disconnect_on_finish:
                    self.close()
                if self.stream is None:
                    raise gen.Return(False)
            except HTTPInputError as e:
                gen_log.info("Malformed HTTP message from %s: %s",
                             self.context, e)
                self.close()
                raise gen.Return(False)
            finally:
                if need_delegate_close:
                    with _ExceptionLoggingContext(app_log):
                        delegate.on_connection_close(self.stream.error)
                self._clear_callbacks()
        raise gen.Return(True)
Exemple #5
0
 def _read_stream_body(self, content_length, delegate):
     while 0 < content_length:
         try:
             body = yield self.stream.read_bytes(
                 min(self.params.chunk_size, content_length), partial=True)
         except StreamClosedError:
             # with partial stream will update close status after receiving
             # the last chunk, so we catch StreamClosedError instead
             raise gen.Return(False)
         content_length -= len(body)
         if not self._write_finished or self.is_client:
             with _ExceptionLoggingContext(app_log):
                 ret = delegate.data_received(body)
                 if ret is not None:
                     yield ret
     raise gen.Return(True)
Exemple #6
0
    def _read_message(self, delegate):
        try:
            while True:
                message_future = self.stream.read_until(b"\r\n")
                if self.timeout is None:
                    message_data = yield message_future
                else:
                    try:
                        message_data = yield gen.with_timeout(
                            self.stream.io_loop.time() + self.timeout,
                            message_future,
                            io_loop=self.stream.io_loop,
                            quiet_exceptions=iostream.StreamClosedError)
                    except gen.TimeoutError:
                        self.close()
                        raise gen.Return(False)

                with _ExceptionLoggingContext(app_log):
                    data = delegate.data_received(message_data)
                    self.stream.write(data)
        finally:
            self._clear_callbacks()
Exemple #7
0
 def _read_body_until_close(self, delegate):
     body = yield self.stream.read_until_close()
     self._read_finished = True
     if not self._write_finished or self.is_client:
         with _ExceptionLoggingContext(app_log):
             delegate.data_received(body)
Exemple #8
0
    def _read_message(self, delegate):
        need_delegate_close = False
        
        try:
           
            '''header_future = self.stream.read_until_regex(
                "\x00",
                max_bytes=3)
            if self.params.header_timeout is None:
                header_data = yield header_future
            else:
                try:
                    header_data = yield gen.with_timeout(
                        self.stream.io_loop.time() + self.params.header_timeout,
                        header_future,
                        io_loop=self.stream.io_loop,
                        quiet_exceptions=iostream.StreamClosedError)
                except gen.TimeoutError:
                    self.close()
                    raise gen.Return(False)'''
            """start_line, headers = self._parse_headers(header_data)
            if self.is_client:
                start_line = httputil.parse_response_start_line(start_line)
                self._response_start_line = start_line
            else:
                start_line = httputil.parse_request_start_line(start_line)
                self._request_start_line = start_line
                self._request_headers = headers
            self._disconnect_on_finish = not self._can_keep_alive(
                start_line, headers)
            """
            yield self._read_body_until_close(delegate)

            need_delegate_close = True
            '''with _ExceptionLoggingContext(app_log):
                header_future = delegate.headers_received(start_line, headers)
                if header_future is not None:
                    yield header_future
            if self.stream is None:
                # We've been detached.
                need_delegate_close = False
                raise gen.Return(False)
            skip_body = False
            if self.is_client:
                if (self._request_start_line is not None and
                        self._request_start_line.method == 'HEAD'):
                    skip_body = True
                code = start_line.code
                if code == 304:
                    # 304 responses may include the content-length header
                    # but do not actually have a body.
                    # http://tools.ietf.org/html/rfc7230#section-3.3
                    skip_body = True
                if code >= 100 and code < 200:
                    # 1xx responses should never indicate the presence of
                    # a body.
                    if ('Content-Length' in headers or
                        'Transfer-Encoding' in headers):
                        raise httputil.HTTPInputError(
                            "Response code %d cannot have body" % code)
                    # TODO: client delegates will get headers_received twice
                    # in the case of a 100-continue.  Document or change?
                    yield self._read_message(delegate)
            else:
                if (headers.get("Expect") == "100-continue" and
                        not self._write_finished):
                    self.stream.write(b"HTTP/1.1 100 (Continue)\r\n\r\n")
            if not skip_body:
                body_future = self._read_body(
                    start_line.code if self.is_client else 0, headers, delegate)
                if body_future is not None:
                    if self._body_timeout is None:
                        yield body_future
                    else:
                        try:
                            yield gen.with_timeout(
                                self.stream.io_loop.time() + self._body_timeout,
                                body_future, self.stream.io_loop,
                                quiet_exceptions=iostream.StreamClosedError)
                        except gen.TimeoutError:
                            gen_log.info("Timeout reading body from %s",
                                         self.context)
                            self.stream.close()
                            raise gen.Return(False)'''
            #self._read_finished = True
            if not self._write_finished or self.is_client:
                need_delegate_close = False
                with _ExceptionLoggingContext(app_log):
                    
                    delegate.finish()
            # If we're waiting for the application to produce an asynchronous
            # response, and we're not detached, register a close callback
            # on the stream (we didn't need one while we were reading)
            if (not self._finish_future.done() and
                    self.stream is not None and
                    not self.stream.closed()):
                self.stream.set_close_callback(self._on_connection_close)
                yield self._finish_future
            if self.is_client and self._disconnect_on_finish:
                self.close()
            if self.stream is None:
                raise gen.Return(False)
        except httputil.HTTPInputError as e:
            gen_log.info("Malformed HTTP message from %s: %s",
                         self.context, e)
            self.close()
            raise gen.Return(False)
        finally:
            if need_delegate_close:
                with _ExceptionLoggingContext(app_log):
                    delegate.on_connection_close()
            self._clear_callbacks()
        raise gen.Return(True)