"""HTTP servlets"""
import os, socket, errno
import BaseHTTPServer
from ThreadedAppServer import Handler
from ASStreamOut import ASStreamOut
class HTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    """Handles incoming requests.
    Recreated with every request. Abstract base class.
    """
    
    
    
    
    def handleRequest(self):
        """Handle a request.
        Actually performs the request, creating the environment and calling
        self.doTransaction(env, input) to perform the response.
        """
        self.server_version = 'Webware/' + self._server.version()
        env = {}
        for header in ('Content-Type', 'Content-Length', 'If-Modified-Since'):
            
            if header in self.headers:
                env[header.upper().replace('-', '_')] = self.headers[header]
                del self.headers[header]
        self.headersToEnviron(self.headers, env)
        env['REMOTE_ADDR'], env['REMOTE_PORT'] = map(str, self.client_address)
        env['REQUEST_METHOD'] = self.command
        path = self.path
        if '?' in path:
            env['REQUEST_URI'], env['QUERY_STRING'] = path.split('?', 1)
        else:
            env['REQUEST_URI'] = path
            env['QUERY_STRING'] = ''
            env['SCRIPT_NAME'] = ''
        env['PATH'] = os.getenv('PATH', '')
        env['PATH_INFO'] = env['REQUEST_URI']
        env['SERVER_ADDR'], env['SERVER_PORT'] = map(str, self._serverAddress)
        env['SERVER_SOFTWARE'] = self.server_version
        env['SERVER_PROTOCOL'] = self.protocol_version
        env['GATEWAY_INTERFACE'] = 'CGI/1.1'
        self.doTransaction(env, self.rfile)
    do_GET = do_POST = do_HEAD = handleRequest
    
    do_OPTIONS = do_PUT = do_DELETE = handleRequest
    do_MKCOL = do_COPY = do_MOVE = handleRequest
    do_PROPFIND = handleRequest
    @staticmethod
    def headersToEnviron(headers, env):
        """Convert headers to environment variables.
        Use a simple heuristic to convert all the headers to
        environmental variables.
        """
        for header, value in headers.items():
            env['HTTP_%s' % header.upper().replace('-', '_')] = value
        return env
    def processResponse(self, data):
        """Process response.
        Takes a string (like what a CGI script would print) and
        sends the actual HTTP response (response code, headers, body).
        """
        status, data = data.split('\r\n', 1)
        status, code, message = status.split(None, 2)
        try:
            assert status == 'Status:'
            code = int(code)
            assert 2 <= code/100 < 6
        except Exception:
            print '%5d  HTTPServer error: Missing status header' % (
                self._requestID,)
        else:
            self.send_response(code, message)
            self.wfile.write(data)
    def log_request(self, code='-', size='-'):
        """Log an accepted request.
        Do nothing (use the LogActivity setting instead).
        """
        pass
class HTTPAppServerHandler(Handler, HTTPHandler):
    """AppServer interface.
    Adapters HTTPHandler to fit with ThreadedAppServer's model of an adapter.
    """
    protocolName = 'http'
    settingPrefix = 'HTTP'
    def handleRequest(self):
        """Handle a request."""
        HTTPHandler.__init__(self, self._sock, self._sock.getpeername(), None)
    def doTransaction(self, env, input):
        """Process transaction."""
        requestDict = dict(format='CGI', environ=env, input=input)
        self.startRequest(requestDict)
        streamOut = ASStreamOut()
        self.dispatchRawRequest(requestDict, streamOut)
        try:
            self.processResponse(streamOut._buffer)
            self._sock.shutdown(2)
        except socket.error, e:
            if e[0] == errno.EPIPE: 
                return
            print '%5d  HTTPServer output error: %s' % (
                self._requestID, e)
        self.endRequest()
    def dispatchRawRequest(self, requestDict, streamOut):
        """Dispatch the request."""
        transaction = self._server._app.dispatchRawRequest(requestDict, streamOut)
        streamOut.close()
        transaction._application = None
        transaction.die()
        del transaction