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()
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()
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()
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()