Exemple #1
0
    def service(self):
        """Execute all pending requests """
        with self.task_lock:
            while self.requests:
                request = self.requests[0]
                if request.error:
                    task = self.error_task_class(self, request)
                else:
                    task = self.task_class(self, request)
                try:
                    task.service()
                except ClientDisconnected:
                    self.logger.warn('Client disconnected when serving %s' %
                                     task.request.path)
                    task.close_on_finish = True
                except:
                    self.logger.exception('Exception when serving %s' %
                                          task.request.path)
                    if not task.wrote_header:
                        if self.adj.expose_tracebacks:
                            body = traceback.format_exc()
                        else:
                            body = ('The server encountered an unexpected '
                                    'internal server error')
                        req_version = request.version
                        req_headers = request.headers
                        request = self.parser_class(self.adj)
                        request.error = InternalServerError(body)
                        # copy some original request attributes to fulfill
                        # HTTP 1.1 requirements
                        request.version = req_version
                        try:
                            request.headers['CONNECTION'] = req_headers[
                                'CONNECTION']
                        except KeyError:
                            pass
                        task = self.error_task_class(self, request)
                        try:
                            task.service()  # must not fail
                        except ClientDisconnected:
                            task.close_on_finish = True
                    else:
                        task.close_on_finish = True
                # we cannot allow self.requests to drop to empty til
                # here; otherwise the mainloop gets confused
                if task.close_on_finish:
                    self.close_when_flushed = True
                    for request in self.requests:
                        request.close()
                    self.requests = []
                else:
                    request = self.requests.pop(0)
                    request.close()

        self.force_flush = True
        self.server.pull_trigger()
        self.last_activity = time.time()
Exemple #2
0
    def service(self):
        """Execute all pending requests """
        with self.task_lock:
            while self.requests:
                request = self.requests[0]
                if request.error:
                    task = self.error_task_class(self, request)
                else:
                    task = self.task_class(self, request)
                try:
                    task.service()
                except:
                    self.logger.exception('Exception when serving %s' %
                                          task.request.path)
                    if not task.wrote_header:
                        if self.adj.expose_tracebacks:
                            body = traceback.format_exc()
                        else:
                            body = ('The server encountered an unexpected '
                                    'internal server error')
                        request = self.parser_class(self.adj)
                        request.error = InternalServerError(body)
                        task = self.error_task_class(self, request)
                        task.service()  # must not fail
                    else:
                        task.close_on_finish = True
                # we cannot allow self.requests to drop to empty til
                # here; otherwise the mainloop gets confused
                if task.close_on_finish:
                    self.close_when_flushed = True
                    for request in self.requests:
                        request._close()
                    self.requests = []
                else:
                    request = self.requests.pop(0)
                    request._close()

        self.force_flush = True
        self.server.pull_trigger()
        self.last_activity = time.time()
Exemple #3
0
    def service(self):
        """Execute one request. If there are more, we add another task to the
        server at the end."""

        request = self.requests[0]

        if request.error:
            task = self.error_task_class(self, request)
        else:
            task = self.task_class(self, request)

        try:
            if self.connected:
                task.service()
            else:
                task.close_on_finish = True
        except ClientDisconnected:
            self.logger.info("Client disconnected while serving %s" % task.request.path)
            task.close_on_finish = True
        except Exception:
            self.logger.exception("Exception while serving %s" % task.request.path)

            if not task.wrote_header:
                if self.adj.expose_tracebacks:
                    body = traceback.format_exc()
                else:
                    body = "The server encountered an unexpected internal server error"
                req_version = request.version
                req_headers = request.headers
                err_request = self.parser_class(self.adj)
                err_request.error = InternalServerError(body)
                # copy some original request attributes to fulfill
                # HTTP 1.1 requirements
                err_request.version = req_version
                try:
                    err_request.headers["CONNECTION"] = req_headers["CONNECTION"]
                except KeyError:
                    pass
                task = self.error_task_class(self, err_request)
                try:
                    task.service()  # must not fail
                except ClientDisconnected:
                    task.close_on_finish = True
            else:
                task.close_on_finish = True

        if task.close_on_finish:
            with self.requests_lock:
                self.close_when_flushed = True

                for request in self.requests:
                    request.close()
                self.requests = []
        else:
            # before processing a new request, ensure there is not too
            # much data in the outbufs waiting to be flushed
            # NB: currently readable() returns False while we are
            # flushing data so we know no new requests will come in
            # that we need to account for, otherwise it'd be better
            # to do this check at the start of the request instead of
            # at the end to account for consecutive service() calls

            if len(self.requests) > 1:
                self._flush_outbufs_below_high_watermark()

            # this is a little hacky but basically it's forcing the
            # next request to create a new outbuf to avoid sharing
            # outbufs across requests which can cause outbufs to
            # not be deallocated regularly when a connection is open
            # for a long time

            if self.current_outbuf_count > 0:
                self.current_outbuf_count = self.adj.outbuf_high_watermark

            request.close()

            # Add new task to process the next request
            with self.requests_lock:
                self.requests.pop(0)

                if self.connected and self.requests:
                    self.server.add_task(self)
                elif (
                    self.connected
                    and self.request is not None
                    and self.request.expect_continue
                    and self.request.headers_finished
                    and not self.sent_continue
                ):
                    # A request waits for a signal to continue, but we could
                    # not send it until now because requests were being
                    # processed and the output needs to be kept in order
                    self.send_continue()

        if self.connected:
            self.server.pull_trigger()

        self.last_activity = time.time()
Exemple #4
0
    def service(self):
        """Execute all pending requests """
        with self.task_lock:
            while self.requests:
                request = self.requests[0]
                if request.error:
                    task = self.error_task_class(self, request)
                else:
                    task = self.task_class(self, request)
                try:
                    task.service()
                except ClientDisconnected:
                    self.logger.info("Client disconnected while serving %s" %
                                     task.request.path)
                    task.close_on_finish = True
                except Exception:
                    self.logger.exception("Exception while serving %s" %
                                          task.request.path)
                    if not task.wrote_header:
                        if self.adj.expose_tracebacks:
                            body = traceback.format_exc()
                        else:
                            body = ("The server encountered an unexpected "
                                    "internal server error")
                        req_version = request.version
                        req_headers = request.headers
                        request = self.parser_class(self.adj)
                        request.error = InternalServerError(body)
                        # copy some original request attributes to fulfill
                        # HTTP 1.1 requirements
                        request.version = req_version
                        try:
                            request.headers["CONNECTION"] = req_headers[
                                "CONNECTION"]
                        except KeyError:
                            pass
                        task = self.error_task_class(self, request)
                        try:
                            task.service()  # must not fail
                        except ClientDisconnected:
                            task.close_on_finish = True
                    else:
                        task.close_on_finish = True
                # we cannot allow self.requests to drop to empty til
                # here; otherwise the mainloop gets confused
                if task.close_on_finish:
                    self.close_when_flushed = True
                    for request in self.requests:
                        request.close()
                    self.requests = []
                else:
                    # before processing a new request, ensure there is not too
                    # much data in the outbufs waiting to be flushed
                    # NB: currently readable() returns False while we are
                    # flushing data so we know no new requests will come in
                    # that we need to account for, otherwise it'd be better
                    # to do this check at the start of the request instead of
                    # at the end to account for consecutive service() calls
                    if len(self.requests) > 1:
                        self._flush_outbufs_below_high_watermark()
                    request = self.requests.pop(0)
                    request.close()

        if self.connected:
            self.server.pull_trigger()
        self.last_activity = time.time()