Hello:
I looked into what it takes to have connections persist (as is default
in HTTP 1.1). The main idea is to save on the SSL handshakes, if using
something like this:
http://pl.atyp.us/wordpress/?p=3232
As it turned out, the main difficulty is in the Python's sample HTTP
server, and presumably all of this is a non-issue if a real webserver
is used. Still, it looks like this:
diff --git a/scripts/hekafsd.py b/scripts/hekafsd.py
index 3936bb4..9819f45 100755
--- a/scripts/hekafsd.py
+++ b/scripts/hekafsd.py
@@ -18,11 +18,14 @@
# along with HekaFS. If not, see <
http://www.gnu.org/licenses/>.
from bottle import route, post, run, view, debug, request, response, \
- TEMPLATE_PATH
+ TEMPLATE_PATH, ServerAdapter
+
+import wsgiref.simple_server as ss
import os
import sys
import socket
+import ssl
import string
import hfs_paths
@@ -237,10 +240,85 @@ def get_style (sheet):
fqpath = sys.argv[0].rsplit('/', 1)
return file("%s/styles/%s" % (fqpath[0], sheet), "r")
+class SecureHandler (ss.WSGIRequestHandler):
+
+ ## Overriding __init__ does not work as one might expect, because
+ ## the initialization of WSGIRequestHandler falls all the way through
+ ## to SocketHandler, and the whole processing happens in __init__.
+ ## Setting protocol_version ahead of the call-down is ineffective
+ ## as it's reset. Setting it after the call-down is ineffective
+ ## because it's too late (uncomment and try it if you don't belive us).
+ ## Fortunately, none of this is necessary because protocol_version
+ ## of an instance is inherited from the class (see below).
+ #def __init__ (self, request, address, srv):
+ # ss.WSGIRequestHandler.__init__(self,request,address,srv)
+ # print "protocol_version at __init__", self.protocol_version
+ # self.protocol_version = "HTTP/1.1"
+
+ def handle (self):
+ ## Keep this part of Jeff's example code for the future.
+ #for part in self.connection.getpeercert()["subject"]:
+ # if part[0][0] == "commonName":
+ # print "### client is %s" % part[0][1]
+ # break
+ #else:
+ # raise ssl.CertificateError, "no matching user"
+
+ # Nothing we can do with parameters permits us to process
+ # several requests per connection otherwise, so we cannot
+ # just tail-call here. Must copy-paste and modify.
+ #ss.WSGIRequestHandler.handle(self) # nope
+
+ # The BaseHTTPRequestHandler has code in handle() that catches
+ # socket.timeout, which ss.WSGIRequestHandler discards.
+ # We do not do that either, for now.
+
+ # In Apache, i counts against MaxKeepAliveRequests, default 100.
+ i = 0;
+ while i < 5: # 100 in Apache. Just do 5 for testing.
+
+ self.raw_requestline = self.rfile.readline()
+ if not self.parse_request():
+ # An error code has been sent, just exit
+ return
+
+ handler = ss.ServerHandler(
+ self.rfile, self.wfile,
+ self.get_stderr(), self.get_environ()
+ )
+ # Set the HTTP version string that is sent over the wire.
+ # Note that it does not affect the way persistent connections
+ # are implemented, only the string that goes out to client.
+ handler.http_version = "1.1"
+ handler.request_handler = self # backpointer for logging
+ handler.run(self.server.get_app())
+
+ if self.close_connection: # Set by parse_request
+ return
+
+ i += 1
+
+class EasySSLServer(ServerAdapter):
+ def run(self, app):
+ handler_cl = SecureHandler
+ # Set the class variable so that parse_request() works.
+ handler_cl.protocol_version = "HTTP/1.1"
+ srv = ss.make_server(self.host, self.port, app,
+ handler_class=handler_cl,
+ **self.options)
+ # TBD: is this the same as "server.pem" above, or different?
+ cert_path = os.path.join(hfs_paths.info_dir,"hekafsd.pem")
+ # srv is ss.WSGIServer, which should be a subclass
+ # of BaseHTTPServer.HTTPServer, subclass of TCPServer that has socket.
+ srv.socket = ssl.wrap_socket(srv.socket,
+ certfile=cert_path, server_side=True)
+ srv.serve_forever()
+
if __name__ == "__main__":
debug(True)
#run(host='0.0.0.0',port=hfs_paths.HEKAFSD_PORT,server=CherryPyServer)
fqpath = sys.argv[0].rsplit('/', 1)
TEMPLATE_PATH.append("%s/views" % fqpath[0])
- run(host='0.0.0.0',port=hfs_paths.HEKAFSD_PORT)
+ #run(host='0.0.0.0',port=hfs_paths.HEKAFSD_PORT)
+ run(host='',port=8443,server=EasySSLServer)
If we were to use it for real, it would also need timing out the connection,
which is what socket.timeout is for.
-- Pete