summaryrefslogtreecommitdiff
path: root/wsgikit/cgiserver.py
diff options
context:
space:
mode:
Diffstat (limited to 'wsgikit/cgiserver.py')
-rw-r--r--wsgikit/cgiserver.py113
1 files changed, 113 insertions, 0 deletions
diff --git a/wsgikit/cgiserver.py b/wsgikit/cgiserver.py
new file mode 100644
index 0000000..33ac0de
--- /dev/null
+++ b/wsgikit/cgiserver.py
@@ -0,0 +1,113 @@
+"""
+cgi WSGI server
+===============
+
+Usage
+-----
+
+The CGI script is the configuration and glue for this server.
+Typically you will write a CGI script like::
+
+ #!/usr/bin/env python
+ from wsgikit.cgiserver import run_with_cgi
+ # Assuming app is your WSGI application object...
+ from myapplication import app
+ run_with_cgi(app)
+
+"""
+
+import os, sys
+
+def run_with_cgi(application,
+ use_cgitb=True,
+ redirect_stdout=False):
+ stdout = sys.stdout
+
+ if use_cgitb:
+ import cgitb
+ cgitb.enable()
+
+ environ = dict(os.environ)
+ environ['wsgi.input'] = sys.stdin
+ environ['wsgi.errors'] = sys.stderr
+ environ['wsgi.version'] = (1, 0)
+ environ['wsgi.multithread'] = False
+ environ['wsgi.multiprocess'] = True
+ environ['wsgi.run_once'] = True
+
+ if os.environ.get('HTTPS', 'off').lower() in ('on', '1'):
+ environ['wsgi.url_scheme'] = 'https'
+ else:
+ environ['wsgi.url_scheme'] = 'http'
+
+ if redirect_stdout:
+ sys.stdout = sys.stderr
+
+ headers_set = []
+ headers_sent = []
+ result = None
+
+ def write(data):
+ assert headers_set, "write() before start_response()"
+
+ if not headers_sent:
+ # Before the first output, send the stored headers
+ status, response_headers = headers_sent[:] = headers_set
+
+ # See if Content-Length is given.
+ found = False
+ for name, value in response_headers:
+ if name.lower() == 'content-length':
+ found = True
+ break
+
+ # If not given, try to deduce it if the iterator implements
+ # __len__ and is of length 1. (data will be result[0] in this
+ # case.)
+ if not found and result is not None:
+ try:
+ if len(result) == 1:
+ response_headers.append(('Content-Length',
+ str(len(data))))
+ except:
+ pass
+
+ stdout.write('Status: %s\r\n' % status)
+ for header in response_headers:
+ stdout.write('%s: %s\r\n' % header)
+ stdout.write('\r\n')
+
+ stdout.write(data)
+ stdout.flush()
+
+ def start_response(status, response_headers, exc_info=None):
+ if exc_info:
+ try:
+ if headers_sent:
+ # Re-raise original exception if headers sent
+ raise exc_info[0], exc_info[1], exc_info[2]
+ finally:
+ exc_info = None # avoid dangling circular ref
+ else:
+ assert not headers_set, "Headers already set!"
+
+ headers_set[:] = [status, response_headers]
+ return write
+
+ result = application(environ, start_response)
+ try:
+ for data in result:
+ if data: # don't send headers until body appears
+ write(data)
+ if not headers_sent:
+ write('') # send headers now if body was empty
+ finally:
+ if hasattr(result, 'close'):
+ result.close()
+
+if __name__ == '__main__':
+ def myapp(environ, start_response):
+ start_response('200 OK', [('Content-Type', 'text/plain')])
+ return ['Hello World!\n']
+
+ run_with_cgi(myapp)