[Zope-Checkins] CVS: Zope3/lib/python/Zope/Server/HTTP - HTTPServer.py:1.1.2.4 HTTPTask.py:1.1.2.3 PublisherHTTPServer.py:1.1.2.3 PublisherHTTPChannel.py:NONE PublisherHTTPTask.py:NONE

Shane Hathaway shane@cvs.zope.org
Thu, 11 Apr 2002 12:29:15 -0400


Update of /cvs-repository/Zope3/lib/python/Zope/Server/HTTP
In directory cvs.zope.org:/tmp/cvs-serv12014

Modified Files:
      Tag: Zope3-Server-Branch
	HTTPServer.py HTTPTask.py PublisherHTTPServer.py 
Removed Files:
      Tag: Zope3-Server-Branch
	PublisherHTTPChannel.py PublisherHTTPTask.py 
Log Message:
- HTTPTask now knows how to build a CGI environment.

- Moved execute() to the server rather than the task and renamed it
executeRequest().  This simplified PublisherHTTPServer and eliminated
the need for two classes.

- Reenabled verification of the status code in the tests, which uncovered
an important oversight in the publisher refactoring.


=== Zope3/lib/python/Zope/Server/HTTP/HTTPServer.py 1.1.2.3 => 1.1.2.4 ===
     SERVER_IDENT = 'Zope.Server.HTTPServer'
 
+    def executeRequest(self, task):
+        """Execute an HTTP request."""
+        # This is a default implementation, meant to be overridden.
+        body = "The HTTP server is running!\r\n" * 10
+        task.response_headers['Content-Type'] = 'text/plain'
+        task.response_headers['Content-Length'] = str(len(body))
+        task.write(body)
 
 
 if __name__ == '__main__':


=== Zope3/lib/python/Zope/Server/HTTP/HTTPTask.py 1.1.2.2 => 1.1.2.3 ===
 
 
+rename_headers = {
+    'CONTENT_LENGTH' : 'CONTENT_LENGTH',
+    'CONTENT_TYPE'   : 'CONTENT_TYPE',
+    'CONNECTION'     : 'CONNECTION_TYPE',
+    }
+
+
 class HTTPTask:
     """An HTTP task accepts a request and writes to a channel.
 
@@ -43,6 +50,7 @@
     accumulated_headers = None
     bytes_written = 0
     auth_user_name = ''
+    cgi_env = None
 
     def __init__(self, channel, request_data):
         self.channel = channel
@@ -66,7 +74,7 @@
         try:
             try:
                 self.start()
-                self.execute()
+                self.channel.server.executeRequest(self)
                 self.finish()
             except socket.error:
                 self.close_on_finish = 1
@@ -155,19 +163,64 @@
         res = '%s\r\n\r\n' % '\r\n'.join(lines)
         return res
 
+    def getCGIEnvironment(self):
+        """Returns a CGI-like environment."""
+        env = self.cgi_env
+        if env is not None:
+            # Return the cached copy.
+            return env
+
+        request_data = self.request_data
+        path = request_data.path
+        channel = self.channel
+        server = channel.server
+
+        while path and path.startswith('/'):
+            path = path[1:]
+
+        env = {}
+        env['REQUEST_METHOD'] = request_data.command.upper()
+        env['SERVER_PORT'] = str(server.port)
+        env['SERVER_NAME'] = server.server_name
+        env['SERVER_SOFTWARE'] = server.SERVER_IDENT
+        env['SERVER_PROTOCOL'] = "HTTP/%s" % self.version
+        env['CHANNEL_CREATION_TIME'] = channel.creation_time
+        env['SCRIPT_NAME']=''
+        env['PATH_INFO']='/' + path
+        query = request_data.query
+        if query:
+            env['QUERY_STRING'] = query
+        env['GATEWAY_INTERFACE'] = 'CGI/1.1'
+        addr = channel.addr[0]
+        env['REMOTE_ADDR'] = addr
+
+        # If the server has a resolver, try to get the
+        # remote host from the resolver's cache.
+        resolver = getattr(server, 'resolver', None)
+        if resolver is not None:
+            dns_cache = resolver.cache
+            if dns_cache.has_key(addr):
+                remote_host = dns_cache[addr][2]
+                if remote_host is not None:
+                    env['REMOTE_HOST'] = remote_host
+
+        env_has = env.has_key
+
+        for key, value in request_data.headers.items():
+            value = value.strip()
+            mykey = rename_headers.get(key, None)
+            if mykey is None:
+                mykey = 'HTTP_%s' % key
+            if not env_has(mykey):
+                env[mykey] = value
+
+        self.cgi_env = env
+        return env
+
     def start(self):
         now = time.time()
         self.start_time = now
         self.response_headers['Date'] = build_http_date (now)
-
-    def execute(self):
-        """
-        Override this.
-        """
-        body = "The HTTP server is running!\r\n" * 10
-        self.response_headers['Content-Type'] = 'text/plain'
-        self.response_headers['Content-Length'] = str(len(body))
-        self.write(body)
 
     def finish(self):
         if not self.wrote_header:


=== Zope3/lib/python/Zope/Server/HTTP/PublisherHTTPServer.py 1.1.2.2 => 1.1.2.3 ===
 
 from HTTPServer import HTTPServer
-from PublisherHTTPChannel import PublisherHTTPChannel
+from Zope.Publisher.Publish import publish
 
 
 class PublisherHTTPServer(HTTPServer):
@@ -25,9 +25,6 @@
 
     __implements__ = HTTPServer.__implements__
 
-    channel_class = PublisherHTTPChannel
-
-
     def __init__(self, request_factory, sub_protocol=None, *args, **kw):
         self.request_factory = request_factory
 
@@ -39,3 +36,12 @@
 
         HTTPServer.__init__(self, *args, **kw)
 
+    def executeRequest(self, task):
+        """Overrides HTTPServer.executeRequest()."""
+        env = task.getCGIEnvironment()
+        instream = task.request_data.getBodyStream()
+
+        request = self.request_factory(instream, task, env)
+        response = request.getResponse()
+        response.setHeaderOutput(task)
+        publish(request)

=== Removed File Zope3/lib/python/Zope/Server/HTTP/PublisherHTTPChannel.py ===

=== Removed File Zope3/lib/python/Zope/Server/HTTP/PublisherHTTPTask.py ===