Пример #1
0
    def _find_service(self):
        self.serv = registry.get_a_service_by_id(self.ident)
        if not self.serv:
            raise KeyError("Nothing known about service %s" % ident)
        #        print >>sys.stderr,"CACHE: %s at %s\n" % (self.ident, self.serv.path)

        hostname, port = global_config.server_address
        if not hostname:
            hostname = "localhost"
        self.baseurl = "http://%s:%d/%s" % (hostname, port, self.serv.path)
Пример #2
0
    def _find_service(self):
        self.serv = registry.get_a_service_by_id(self.ident)
        if not self.serv:
            raise KeyError("Nothing known about service %s" % ident)
#        print >>sys.stderr,"CACHE: %s at %s\n" % (self.ident, self.serv.path)

        hostname,port = global_config.server_address
        if not hostname:
            hostname = "localhost"
        self.baseurl = "http://%s:%d/%s" % (hostname, port, self.serv.path)
Пример #3
0
def _handle_notify(environ, f, service_list):
    for service_id in service_list:
        service = registry.get_a_service_by_id(service_id)
        service_environ = environ.copy()
        service_environ["PATH_INFO"] = service.path
        f.seek(0)
        new_request(service_environ)
        try:
            service.handler(service_environ, ignore_start_response)
        except Exception:
            raise
            # XXX
            pass
Пример #4
0
def _handle_notify(environ, f, service_list):
    for service_id in service_list:
        service = registry.get_a_service_by_id(service_id)
        service_environ = environ.copy()
        service_environ["PATH_INFO"] = service.path
        f.seek(0)
        new_request(service_environ)
        try:
            service.handler(service_environ, ignore_start_response)
        except Exception:
            raise
            # XXX
            pass
Пример #5
0
    def __call__(self, environ, start_response):
        # The WSGI entry point for the pipeline
        
        logger.debug("Started the %s (%s) pipeline", self.ident, self.path)

        # Help capture the response of a WSGI request,
        # so I can forward it as input to the next request.
        captured_response = [None, None, None]
        captured_body_length = None
        def capture_start_response(status, headers, exc_info=None):
            if exc_info is None:
                captured_response[:] = [status, headers, False]
            else:
                captured_response[:] = [status, headers, True]
                # Forward this to the real start_response
                return start_response(status, headers, exc_info)

        num_stages = len(self.stages)
        for stage_index, is_first, is_last, stage in _flag_position(self.stages):
            service = registry.get_a_service_by_id(stage.ident)
            if service is None:
                logger.error("Pipeline %r(%r) could not find a %r service",
                              self.ident, self.path, stage.ident)
                start_response("500 Internal server error", [("Content-Type", "text/plain")])
                return ["Broken internal pipeline.\n"]

            # Construct a new environ for each stage in the pipeline.
            # We have to make a new one since a stage is free to
            # do whatever it wants to the environ. (It does not have
            # free reign over all the contents of the environ.)
            stage_environ = environ.copy()
            if not is_first:
                # The first stage gets the HTTP request method
                # Everything else gets a POST.
                stage_environ["REQUEST_METHOD"] = "POST"
            assert service.path is not None # Can some services/pipelines not be mounted?
            stage_environ["SCRIPT_NAME"] = service.path
            #stage_environ["PATH_INFO"] = ... # I think  this is best left unchanged. XXX

            if is_first:
                # Augment the QUERY_STRING string with any pipeline-defined query string
                # (You probably shouldn't be doing this. Remove this feature? XXX)
                if stage.query_string:
                    if stage_environ["QUERY_STRING"]:
                        stage_environ["QUERY_STRING"] += ("&" + stage.query_string)
                    else:
                        stage_environ["QUERY_STRING"] = stage.query_string
            else:
                # The other stages get nothing about the HTTP query string
                # but may get a pipeline-defined query string
                if stage.query_string:
                    stage_environ["QUERY_STRING"] = stage.query_string
                else:
                    stage_environ["QUERY_STRING"] = ""

            if not is_first:
                # Forward information from the previous stage
                stage_environ["CONTENT_TYPE"] = _find_header("content-type",
                                                             captured_response[1])
                stage_environ["CONTENT_LENGTH"] = captured_body_length
                stage_environ["wsgi.input"] = captured_body

                # Make the previous response headers available to the next stage
                stage_environ["akara.pipeline_headers"] = captured_response[1]

            logger.debug("Pipeline %r(%r) at stage %r (%d/%d)",
                         self.ident, self.path, stage.ident, stage_index+1, num_stages)
            if is_last:
                # End of the pipeline. Let someone else deal with the response
                return service.handler(stage_environ, start_response)
            else:
                # Intermediate stage output. Collect to forward to the next stage
                captured_body = StringIO()
                result = service.handler(stage_environ, capture_start_response)

                # Did start_response get an exc_info term? (It might not
                # have been thrown when forwarded to the real start_response.)
                if captured_response[2]:
                    # It didn't raise an exception. Assume the response contains
                    # the error message. Forward it and stop the pipeline.
                    logger.debug(
                        "Pipeline %r(%r) start_response received exc_info from stage %r. Stopping.",
                        self.ident, self.path, stage.ident)
                    return result

                # Was there some sort of HTTP error?
                status = captured_response[0].split(None, 1)[0]
                # XXX What counts as an error?
                if status not in ("200", "201"):
                    logger.debug(
                        "Pipeline %r(%r) start_response received status %r from stage %r. Stopping.",
                        self.ident, self.path, status, stage.ident)
                    start_response(captured_response[0], captured_response[1])
                    # This should contain error information
                    return result

                # Save the response to the cStringIO
                try:
                    # We might be able to get some better performance using
                    # a wsgi.file_wrapper. If the chunks come from a file-like
                    # object then we can reach in and get that file-like object
                    # instead of copying it to a new one
                    for chunk in result:
                        captured_body.write(chunk)
                finally:
                    # Part of the WSGI spec
                    if hasattr(result, "close"):
                        result.close()
                captured_body_length = captured_body.tell()
                captured_body.seek(0)

        raise AssertionErorr("should never get here")