Ejemplo n.º 1
0
 def __init__(self, conn, request_id, role):
     self.conn = conn
     self.id = request_id
     self.role = role
     self.stdin = InputStream()
     self.stdout = OutputStream(conn, request_id, FCGI_STDOUT)
     self.stderr = OutputStream(conn, request_id, FCGI_STDERR)
     self.greenlet = None
     self.environ_list = []
     self.environ = {}
     self.status = None
     self.headers = None
     self.headers_sent = False
Ejemplo n.º 2
0
class Request(object):

    def __init__(self, conn, request_id, role):
        self.conn = conn
        self.id = request_id
        self.role = role
        self.stdin = InputStream()
        self.stdout = OutputStream(conn, request_id, FCGI_STDOUT)
        self.stderr = OutputStream(conn, request_id, FCGI_STDERR)
        self.greenlet = None
        self.environ_list = []
        self.environ = {}
        self.status = None
        self.headers = None
        self.headers_sent = False

    def run(self, app):
        environ = self.make_environ()

        try:
            app_iter = app(environ, self.start_response)
        except:
            app_iter = self.handle_error()
        
        # do nothing until first non-empty chunk
        write = self.stdout.write
        started = self.headers_sent
        for chunk in app_iter:
            if not chunk:
                continue
            if not started:
                started = True
                self.send_headers()
            write(chunk)

        if not started:
            self.send_headers()

        self.stdout.close()
        self.stderr.close()

        if hasattr(app_iter, 'close'):
            app_iter.close()

    def make_environ(self):
        env = self.environ
        
        for name in MANDATORY_WSGI_ENVIRON_VARS.difference(env):
            env[name] = ''

        env['wsgi.version'] = (1, 0)
        env['wsgi.input'] = self.stdin
        env['wsgi.errors'] = self.stderr
        env['wsgi.multithread'] = True
        env['wsgi.multiprocess'] = False
        env['wsgi.run_once'] = False

        https = env.get('HTTPS','').lower()
        if https in ('yes', 'on', '1'):
            env['wsgi.url_scheme'] = 'https'
        else:
            env['wsgi.url_scheme'] = 'http'

        return env

    def start_response(self, status, headers, exc_info=None):
        if exc_info is not None:
            try:
                if self.headers_sent:
                    raise exc_info[1]
            finally:
                exc_info = None
        else:
            assert status is not None
            assert self.status is None

        self.status = status
        self.headers = headers

        return self.write_from_app

    def send_headers(self):
        data = ['Status: %s' % self.status]
        data.extend('%s: %s' % hdr for hdr in self.headers)
        data.append('\r\n')
        self.stdout.write('\r\n'.join(data))
        self.headers_sent = True

    def write_from_app(self, chunk):
        if not chunk:
            return
        if not self.headers_sent:
            self.send_headers()
        self.stdout.write(chunk)

    def handle_error(self):
        exc_info = sys.exc_info()
        logger.exception('Application raised exception')
        self.start_response('500 Internal Server Error', [('Content-type', 'text/plain')], exc_info)
        error_iter = format_exception(*exc_info)
        self.stderr.writelines(error_iter)
        return error_iter