示例#1
0
文件: asvr.py 项目: pastebt/yeast
 def __init__(self, sock, addr):
     Acore.__init__(self)
     self.addr = addr
     self.ahttp = AHTTP(sock, user=self)
示例#2
0
文件: asvr.py 项目: pastebt/yeast
class WsgiHandler(Acore):
    app = None
    env = {'SERVER_NAME': 'yeast asvr 0.1',
           #'GATEWAY_INTERFACE'] = 'CGI/1.1'
           'SERVER_PORT': '8080',
           'SCRIPT_NAME': '',
          }

    def __init__(self, sock, addr):
        Acore.__init__(self)
        self.addr = addr
        self.ahttp = AHTTP(sock, user=self)

    def setup_env(self):
        env = self.environ = self.env.copy()
        http_dict = self.ahttp.http_dict
        hs = http_dict['headers']
        env['yeast.SELF'] = self
        env['yeast.AHTTP'] = self.ahttp
        #env['HTTP_HEADERS'] = hs
        env['REMOTE_ADDR'] = self.addr[0]
        env['REMOTE_PORT'] = self.addr[1]
        if hs.typeheader is None:
            env['CONTENT_TYPE'] = hs.type
        else:
            env['CONTENT_TYPE'] = hs.typeheader
        l = hs.getheader('content-length')
        if l:
            env['CONTENT_LENGTH'] = l
        env['SERVER_PROTOCOL'] = http_dict['version']
        env['REQUEST_METHOD'] = http_dict['action']
        env['REQUEST_PATH'] = path = http_dict['path']

        pq = path.split('?', 1)
        p, q = pq[0], pq[1] if len(pq) == 2 else ''

        env['PATH_INFO'] = urllib.unquote(p)
        env['QUERY_STRING'] = q

        for k, v in hs.items():
            k = k.replace('-', '_').upper()
            v = v.strip()
            if k in env:
                continue                     # skip content length, type,etc.
            if 'HTTP_' + k in env:
                env['HTTP_' + k] += ',' + v  # comma-separate multiple headers
            else:
                env['HTTP_' + k] = v

    def wsgi_write(self, data):
        self._buf.write(data)
        self.sent_size += len(data)

    def start_response(self, status, headers, exc_info=None):
        self._buf = StringIO()
        self.sent_size = 0
        self.app_status = status
        self.app_headers = headers
        return self.wsgi_write

    def handle_error(self):
        #self.start_response()
        pass

    def get_body(self):
        #print int(self.environ.get('CONTENT_LENGTH', 0))
        if int(self.environ.get('CONTENT_LENGTH', 0)) > 0:
            for y in self.ahttp.get_body():
                yield y
        #else:
        #    self.ahttp.http_dict['body'] = StringIO()

    def _run(self):
        #assert isinstance(self.app, callable)
        try:
            for y in self.ahttp.get_head():
                yield y
        except SocketClosed:
            self.ahttp.sock.close()
            logging.debug("%s SocketClosed" % str(self.addr))
            return
        self.setup_env()

        for y in self.get_body():
            yield y

        self.result = self.app(self.environ, self.start_response)
        #print repr(self.result)
        for x in self.result:
            if isinstance(x, Aact):
                yield x
            else:
                self.wsgi_write(x)

        # process http status and headers
        msg = StringIO()
        msg.write("%s %d OK\r\n" % (
                   self.ahttp.http_dict['version'], self.app_status))

        # FIXME? is this the right way?
        self.app_headers['Content-Length'] = self.sent_size

        for h, v in self.app_headers.iteritems():
            msg.write("%s: %s\r\n" % (h, v))
        msg.write('\r\n')
        for y in self.ahttp.write_all(msg.getvalue()):
            yield y
        # http body
        for y in self.ahttp.write_all(self._buf.getvalue()):
            yield y
        # FIXME
        self.ahttp.sock.close()

    def run(self):
        try:
            for y in self._run():
                yield y
        except Exception, e:
            logging.error("self.addr = %s" % str(self.addr))
            logexc()