summaryrefslogtreecommitdiff
path: root/src/wsgiref/handlers.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/wsgiref/handlers.py')
-rw-r--r--src/wsgiref/handlers.py76
1 files changed, 38 insertions, 38 deletions
diff --git a/src/wsgiref/handlers.py b/src/wsgiref/handlers.py
index 287e3bb..2cc8fed 100644
--- a/src/wsgiref/handlers.py
+++ b/src/wsgiref/handlers.py
@@ -1,10 +1,10 @@
"""Base classes for server/gateway implementations"""
from types import StringType
-from util import FileWrapper, guess_scheme
+from util import FileWrapper, guess_scheme, is_hop_by_hop
from headers import Headers
-import sys, os
+import sys, os, time
try:
dict
@@ -48,6 +48,10 @@ class BaseHandler:
wsgi_multiprocess = True
wsgi_run_once = False
+ origin_server = True # We are transmitting direct to client
+ http_version = "1.0" # Version that should be used for response
+ server_software = None # String name of server software, if any
+
# os_environ is used to supply configuration from the OS environment:
# by default it's a copy of 'os.environ' as of import time, but you can
# override this in e.g. your __init__ method.
@@ -76,10 +80,6 @@ class BaseHandler:
-
-
-
-
def run(self, application):
"""Invoke the application"""
# Note to self: don't move the close()! Asynchronous servers shouldn't
@@ -151,17 +151,17 @@ class BaseHandler:
if blocks==1:
self.headers['Content-Length'] = str(self.bytes_sent)
return
- # XXX Try for chunked encoding if enabled
+ # XXX Try for chunked encoding if origin server and client is 1.1
def cleanup_headers(self):
- """Make any necessary header changes or defaults"""
+ """Make any necessary header changes or defaults
+
+ Subclasses can extend this to add other defaults.
+ """
if not self.headers.has_key('Content-Length'):
self.set_content_length()
- # XXX set up Date, Server headers
-
-
def start_response(self, status, headers,exc_info=None):
"""'start_response()' callable as specified by PEP 333"""
@@ -183,25 +183,25 @@ class BaseHandler:
for name,val in headers:
assert type(name) is StringType,"Header names must be strings"
assert type(val) is StringType,"Header values must be strings"
-
+ assert not is_hop_by_hop(name),"Hop-by-hop headers not allowed"
self.status = status
self.headers = self.headers_class(headers)
return self.write
-
-
-
-
-
-
-
-
-
-
-
-
-
+ def send_preamble(self):
+ """Transmit version/status/date/server, via self._write()"""
+ if self.origin_server:
+ if self.client_is_modern():
+ self._write('HTTP/%s %s\r\n' % (self.http_version,self.status))
+ if not self.headers.has_key('Date'):
+ self._write(
+ 'Date: %s\r\n' % time.asctime(time.gmtime(time.time()))
+ )
+ if self.server_software and not self.headers.has_key('Server'):
+ self._write('Server: %s\r\n' % self.server_software)
+ else:
+ self._write('Status: %s\r\n' % self.status)
def write(self, data):
"""'write()' callable as specified by PEP 333"""
@@ -265,18 +265,13 @@ class BaseHandler:
self.bytes_sent = 0; self.headers_sent = False
- def send_status(self):
- """Transmit the status to the client, via self._write()
-
- (BaseCGIHandler overrides this to use a "Status:" prefix.)"""
- self._write('%s\r\n' % status)
-
def send_headers(self):
"""Transmit headers to the client, via self._write()"""
self.cleanup_headers()
self.headers_sent = True
- self.send_status()
- self._write(str(self.headers))
+ if not self.origin_server or self.client_is_modern():
+ self.send_preamble()
+ self._write(str(self.headers))
def result_is_file(self):
@@ -285,6 +280,11 @@ class BaseHandler:
return wrapper is not None and isinstance(self.result,wrapper)
+ def client_is_modern(self):
+ """True if client can accept status and headers"""
+ return self.environ['SERVER_PROTOCOL'].upper() != 'HTTP/0.9'
+
+
def log_exception(self,exc_info):
"""Log the 'exc_info' tuple in the server log
@@ -308,6 +308,7 @@ class BaseHandler:
self.finish_response()
# XXX else: attempt advanced recovery techniques for HTML or text?
+
def error_output(self, environ, start_response):
"""WSGI mini-app to create error output
@@ -325,7 +326,6 @@ class BaseHandler:
return [self.error_body]
-
# Pure abstract methods; *must* be overridden in subclasses
def _write(self,data):
@@ -384,7 +384,7 @@ class BaseCGIHandler(BaseHandler):
'multiprocess' (defaulting to 'True' and 'False' respectively) to control
the configuration sent to the application.
"""
-
+ origin_server = False
wsgi_multithread = False
wsgi_multiprocess = True
@@ -416,9 +416,6 @@ class BaseCGIHandler(BaseHandler):
self.stdout.flush()
self._flush = self.stdout.flush
- def send_status(self):
- self._write('Status: %s\r\n' % self.status)
-
class CGIHandler(BaseCGIHandler):
"""CGI-based invocation via sys.stdin/stdout/stderr and os.environ
@@ -449,3 +446,6 @@ class CGIHandler(BaseCGIHandler):
+
+
+