예제 #1
0
파일: Task.py 프로젝트: chadwhitacre/public
    def fail(self):
        """Still return a response in cases of extreme failure.
        """

        log(90, "Critical error:\n%s" % traceback.format_exc())

        # Build the response.
        # ===================

        status_line = "%s %d %s\r\n" % (self.server.http_version_string, 500,
                                        "Internal Server Error")

        if self.server.deploy_mode:
            body = "Internal Server Error"
        else:
            body = "Internal Server Error\r\n\r\n%s" % traceback.format_exc()

        headers = {}
        headers['Content-Length'] = len(body)
        headers['Content-Type'] = 'text/plain'

        # Send the response.
        # ==================

        self.channel.write(status_line)
        for header in sorted(headers.items()):
            self.channel.write('%s: %s\r\n' % header)
        self.channel.write('\r\n')
        self.channel.write(body)
예제 #2
0
 def stop(self, signum=-1, frame=None):
     """Stop the child process, then exit ourselves.
     """
     self.stop_child()
     if signum is not None:
         log(1, "parent caught %s" % STOP_SIGNALS[signum])
     log(1, "parent shutting down...")
     raise SystemExit
예제 #3
0
파일: Task.py 프로젝트: chadwhitacre/public
    def process(self):
        """Execute one transaction.

        The call to Transaction.process is complicated by the fact that in
        development mode we want to drop into the post-mortem debugger when
        there is an exception (other than Response, of course).

        Transaction.process is expected to raise a Response or other exception.

        """

        config = TransactionConfig(self.app, self.server_config)

        # Do some late validation so we can use Response.
        # ===============================================

        resource_fs_path = uri_to_fs(config, self.request.path, raw=True)

        # Is the app still on the filesystem?
        if not os.path.isdir(config.app_fs_root):
            raise Response(404)

        if config.__:

            # Is the app's magic directory still on the filesystem?
            if not os.path.isdir(config.__):
                response = Response(500)
                response.body = ("The application's magic directory has " +
                                 "disappeared.")
                raise response

            # Protect the magic directory from direct access.
            if resource_fs_path.startswith(config.__):
                raise Response(404)

        # Get out of the way.
        # ===================

        transaction = self.app.module.Transaction(config)
        if not self.dev_mode:
            transaction.process(self.request)
        else:
            try:
                transaction.process(self.request)
            except Response:
                raise
            except:
                log(90, traceback.format_exc())
                pdb.post_mortem(sys.exc_info()[2])
                raise

        # You know something? No soup for you!
        # ====================================

        response = Response(500)
        response.body = "%s.process did not raise anything." % str(transaction)
        raise response
예제 #4
0
파일: Task.py 프로젝트: chadwhitacre/public
    def respond(self):
        """Execute one transaction.

        The call to Application.respond is complicated by the fact that in
        debugging mode we want to drop into the post-mortem debugger when there
        is an exception (other than Response, of course).

        Application.respond is expected to raise a Response or other exception.

        """

        # Do some late validation so we can use Response.
        # ===============================================

        resource_fs_path = uri_to_fs(self.app.site_root,
                                     self.app.fs_root,
                                     self.app.uri_root,
                                     self.request.path,
                                     raw=True)

        # Is the app still on the filesystem?
        if not os.path.isdir(self.app.fs_root):
            raise Response(404)

        if self.app.__:

            # Is the app's magic directory still on the filesystem?
            if not os.path.isdir(self.app.__):
                raise Response(
                    500,
                    "The application's magic directory has " + "disappeared.")

            # Protect the magic directory from direct access.
            if resource_fs_path.startswith(self.app.__):
                raise Response(404)

        # Get out of the way.
        # ===================

        if not self.server.debug_mode:
            self.app.respond(self.request)
        else:
            try:
                self.app.respond(self.request)
            except Response:
                raise
            except:
                log(90, traceback.format_exc())
                pdb.post_mortem(sys.exc_info()[2])
                raise

        # You know something? No soup for you!
        # ====================================

        raise Response(
            500, "%s.respond did not raise " % str(application) + "anything.")
예제 #5
0
파일: Task.py 프로젝트: chadwhitacre/public
    def get_app(self):
        """Get an application with which to serve the requested URI.
        """

        app = None
        for _app in self.server.config.apps:
            if self.request.path.startswith(_app.uri_root):
                app = _app
                break
        if app is None:
            # This catches, e.g., ../../../../../../../../../etc/master.passwd
            raise StandardError("Unable to find an application to serve " +
                                "%s." % self.request.path)

        log(98, "Using %s for this request" % app)
        return app
예제 #6
0
    def stop_child(self):
        """Stop the child server process.
        """
        try:
            os.kill(self.pid, signal.SIGHUP)
        except OSError:
            log(90, "OSError killing pid %d" % self.pid)
            log(99, traceback.format_exc())

        if 0:  # this is for debugging the restart-while-debugging bug

            print "isatty: %s %s %s" % tuple(
                [x.isatty() for x in (sys.stdin, sys.stdout, sys.stderr)])

            while 0:
                msg = os.read(0, 8192)
                if msg == 'quit\n':
                    break
                os.write(1, msg)
예제 #7
0
파일: Task.py 프로젝트: chadwhitacre/public
    def __init__(self, channel, request):
        """Takes an IServerChannel (httpy._zope) and an IRequest (httpy).
        """

        try:
            # Set these early in case we fail.
            self.channel = channel
            self.server = self.channel.server

            # This is where we are likely to fail.
            self.request = Request(request)
            self.app = self.get_app()

            if int(os.environ.get('HTTPY_VERBOSITY', 0)) >= 99:
                request_lines = request.raw.splitlines()
                raw_request = os.linesep.join(request_lines)
                log(99, raw_request)

        except:
            self.fail()
예제 #8
0
 def start(self, args=None):
     log(1, "starting child server ...")
     if args is None:
         args = [sys.executable] + sys.argv
     new_env = os.environ.copy()
     new_env['HTTPY_PLAIN_JANE'] = 'So plain.'
     while 1:
         try:
             try:
                 self.pid = os.spawnve(os.P_NOWAIT, sys.executable, args,
                                       new_env)
                 while 1:
                     self.look_for_changes()
                     time.sleep(1)
             finally:
                 self.stop_child()
         except SystemExit:
             time.sleep(0.1)  # Give stdout a chance to flush.
             raise
         except Restart:
             log(90, "Restarting child server ...")
         except:
             log(
                 90, "Exception while spawning child ...\n" +
                 traceback.format_exc())
예제 #9
0
 def start(self):
     self.accept_connections()
     try:
         addr, port = self.socket.getsockname()
         log(1, "httpy started on port %s" % port)
         log(99, "%s\n\n" % ("="*76))
         asyncore.loop(timeout=5)
     except KeyboardInterrupt:
         log(1, "shutting down...")
         self.task_dispatcher.shutdown()
예제 #10
0
 def stop(self, signum=None, frame=None):
     if signum is not None:
         log(1, "caught %s" % STOP_SIGNALS[signum])
     log(1, "shutting down...")
     for app in self.config.apps:
         if hasattr(app, 'close') and inspect.ismethod(app.close):
             app.close()
     self.task_dispatcher.shutdown()
     asyncore.close_all()
     log(1, "httpy stopped")
예제 #11
0
파일: Task.py 프로젝트: chadwhitacre/public
    def deliver(self, response):
        """Given an httpy.Response, write it out to the wire.
        """

        log(96, "Attempting to send a response")
        log(99, "Response lineage as follows:\n%s" % traceback.format_exc())

        # Output the Status-Line.
        # =======================

        if response.code not in StatusCodes:
            raise StandardError("Bad response code: %r" % response.code)
        elif (response.code == 537) and self.server.deploy_mode:
            raise StandardError("Won't serve 537 in deployment mode.")
        reason_phrase, reason_message = StatusCodes.get(response.code)
        status_line = ' '.join((str(self.server.http_version_string),
                                str(response.code), reason_phrase))
        self.channel.write(status_line + '\r\n')

        # Generate the body.
        # ==================
        # We do this here so we can calculate the content-length.

        if (not response.body) and (response.code not in (200, 537)):
            response.body = reason_message
        if response.code == 537:
            if not isinstance(response.body, basestring):
                response.body = pprint.pformat(response.body)
        response.body = str(response.body)

        # Output the headers.
        # ===================
        # First we convert all headers to lower case so that we can index them
        # sanely. We then ensure a minimal set of headers, overriding any
        # existing content-length because we don't trust it.

        headers = {}
        for k, v in response.headers.iteritems():
            header = k.lower()
            if header == 'content-length':
                continue
            headers[header] = v

        if 'content-length' not in headers:  # always true
            headers['content-length'] = len(response.body)
        if 'content-type' not in headers:
            if str(response.code).startswith('2'):
                # Setting this header for successful requests is the
                # application's job.
                headers['content-type'] = 'application/octet-stream'
            else:
                # But error messages default to text/plain.
                headers['content-type'] = 'text/plain'
        if 'server' not in headers:
            headers['server'] = self.server.response_header

        for header in headers.iteritems():
            self.channel.write("%s: %s\r\n" % header)

        self.channel.write('\r\n')

        # Output the body.
        # ================
        # We don't output the body for 304s or HEAD requests, but we always do
        # for Request parsing errors.

        if (response.code != 304) and (self.request.method != 'HEAD'):
            self.channel.write(response.body)

        log(
            94, "Responded to %s with %d %s" %
            (self.request.raw_line, response.code, reason_phrase))
        log(99, "%s\n\n" % ("=" * 76))
예제 #12
0
 def start(self):
     self.accept_connections()
     addr, port = self.socket.getsockname()
     log(1, "httpy started on port %s" % port)
     log(99, "%s\n\n" % ("=" * 76))
     asyncore.loop(timeout=5)