Description of problem:
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:
Version-Release number of selected component (if applicable):
Steps to Reproduce:
diff --git a/scripts/hekafsd.py b/scripts/hekafsd.py
index 3936bb4..9819f45 100755
@@ -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, ServerAdapter
+import wsgiref.simple_server as ss
@@ -237,10 +240,85 @@ def get_style (sheet):
fqpath = sys.argv.rsplit('/', 1)
return file("%s/styles/%s" % (fqpath, 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 == "commonName":
+ # print "### client is %s" % part
+ # break
+ # 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
+ 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
+ if self.close_connection: # Set by parse_request
+ i += 1
+ 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,
+ # 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)
if __name__ == "__main__":
fqpath = sys.argv.rsplit('/', 1)
TEMPLATE_PATH.append("%s/views" % fqpath)
Note that "I" in 'I looked into what it takes to have connections persist ...' is Peter Zaitcev
Nice work untangling the contorted WSGI control flows. Some questions/answers/issues:
(1) The certfile argument is the same as "server.pem" in the original example, but the other wrap_socket arguments in that example - keyfile, cert_reqs, ca_certs - are also required. Giving out a cert with no key, or blindly accepting others' certs, is not consistent with secure operation.
(2) Setting SecureHandler.protocol_version (which is a class constant rather than an instance variable) could be done more cleanly, readably, and efficiently from within the SecureHandler definition itself than by reaching in from EasySSLServer.run every time it's called.
(3) Please don't change (and hard-code) the port that the service runs on.
(4) There have been recent commits on master (e.g. fec3f79b8a3078c28a6c5ad372a578ab4ad2d935) which might cause application of this patch to fail, so please rebase before re-submitting.
HekaFS will be merged into core GlusterFS