import os, socket, time, 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. """ # This sends the common CGI variables, except the following: # HTTP_CONNECTION, HTTP_KEEP_ALIVE # DOCUMENT_ROOT, PATH_TRANSLATED, SCRIPT_FILENAME # SERVER_NAME, SERVER_ADMIN, SERVER_SIGNATURE 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 = {} if self.headers.has_key('Content-Type'): env['CONTENT_TYPE'] = self.headers['Content-Type'] del self.headers['Content-Type'] if self.headers.has_key('Content-Length'): env['CONTENT_LENGTH'] = self.headers['Content-Length'] del self.headers['Content-Length'] key = 'If-Modified-Since' if self.headers.has_key(key): env[key] = self.headers[key] del self.headers[key] 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 path.find('?') != -1: 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 # These methods are used in WebDAV requests: do_OPTIONS = do_PUT = do_DELETE = handleRequest do_MKCOL = do_COPY = do_MOVE = handleRequest do_PROPFIND = handleRequest def headersToEnviron(self, 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 = { '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: # broken pipe 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