Search code examples
pythonpython-2.7objectsslhttplib

How to serialize a httplib SSL connection object in python?


I am trying to send a httplib connection object over a zmq socket, but I am getting the following error TypeError: can't pickle _ssl._SSLSocket objects.

Now I thought this would have been the case as I am just experimenting at the moment, but does anyone know of a method to wrap or serialize the SSL object so that I can send it to other threads, over sockets?

An example use case:

#Script 1
import zmq
ctx = zmq.Context()
GLOBAL_SOCKET=ctx.socket(zmq.PUB)
GLOBAL_SOCKET.bind('tcp://127.0.0.1:2000')

conn = httplib.HTTPSConnection('site...')
GLOBAL_SOCKET.send_pyobj(conn)


#script 2
import zmq
ctx = zmq.Context()
GLOBAL_SOCKET=ctx.socket(zmq.SUB)
GLOBAL_SOCKET.connect('tcp://127.0.0.1:2000')
GLOBAL_SOCKET.setsockopt(zmq.SUBSCRIBE, '')

#recv SSL object in response hopefully
conn_ = GLOBAL_SOCKET.recv_pyobj()

#work with the connection object in another thread
conn_.request('GET', ....)
conn_.request.getresponse()

Any help welcome.


Solution

  • a working example using multiprocessing.Queue:

    import httplib
    import ssl
    import copy_reg
    from multiprocessing.reduction import rebuild_socket, reduce_socket
    from multiprocessing import Queue
    import os
    
    
    def save_sslcontext(obj):
        return obj.__class__, (obj.protocol,)
    
    copy_reg.pickle(ssl.SSLSocket, reduce_socket, rebuild_socket)
    copy_reg.pickle(ssl.SSLContext, save_sslcontext)
    
    
    def parent():
        conn = httplib.HTTPSConnection('www.baidu.com')
        conn.connect()
        queue.put(conn)
        os.wait()
    
    
    def child():
        conn = queue.get()
        conn.request('GET', '/')
        r = conn.getresponse()
        print r.status
    
    
    queue = Queue()
    if 0 == os.fork():
        child()
    else:
        parent()