Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Branch: master
Fetching contributors…

Cannot retrieve contributors at this time

156 lines (99 sloc) 3.953 kB
# This is the Twisted Poetry Proxy, version 3.0
import optparse
from twisted.internet.defer import Deferred, succeed
from twisted.internet.protocol import ClientFactory, ServerFactory, Protocol
def parse_args():
usage = """usage: %prog [options] [hostname]:port
This is the Poetry Proxy, version 3.0.
python poetry-proxy.py [hostname]:port
If you are in the base directory of the twisted-intro package,
you could run it like this:
python twisted-server-4/poetry-proxy.py 10000
to proxy the poem for the server running on port 10000.
"""
parser = optparse.OptionParser(usage)
help = "The port to listen on. Default to a random available port."
parser.add_option('--port', type='int', help=help)
help = "The interface to listen on. Default is localhost."
parser.add_option('--iface', help=help, default='localhost')
options, args = parser.parse_args()
if len(args) != 1:
parser.error('Provide exactly one server address.')
def parse_address(addr):
if ':' not in addr:
host = '127.0.0.1'
port = addr
else:
host, port = addr.split(':', 1)
if not port.isdigit():
parser.error('Ports must be integers.')
return host, int(port)
return options, parse_address(args[0])
class PoetryProxyProtocol(Protocol):
def connectionMade(self):
self.deferred = self.factory.service.get_poem()
self.deferred.addCallback(self.transport.write)
self.deferred.addBoth(lambda r: self.transport.loseConnection())
def connectionLost(self, reason):
if self.deferred is not None:
deferred, self.deferred = self.deferred, None
deferred.cancel() # cancel the deferred if it hasn't fired
class PoetryProxyFactory(ServerFactory):
protocol = PoetryProxyProtocol
def __init__(self, service):
self.service = service
class PoetryClientProtocol(Protocol):
poem = ''
def dataReceived(self, data):
self.poem += data
def connectionLost(self, reason):
self.poemReceived(self.poem)
def poemReceived(self, poem):
self.factory.poem_finished(poem)
class PoetryClientFactory(ClientFactory):
protocol = PoetryClientProtocol
def __init__(self, deferred):
self.deferred = deferred
def poem_finished(self, poem):
if self.deferred is not None:
d, self.deferred = self.deferred, None
d.callback(poem)
def clientConnectionFailed(self, connector, reason):
if self.deferred is not None:
d, self.deferred = self.deferred, None
d.errback(reason)
class ProxyService(object):
poem = None # the cached poem
def __init__(self, host, port):
self.host = host
self.port = port
def get_poem(self):
if self.poem is not None:
print 'Using cached poem.'
# return an already-fired deferred
return succeed(self.poem)
def canceler(d):
print 'Canceling poem download.'
factory.deferred = None
connector.disconnect()
print 'Fetching poem from server.'
deferred = Deferred(canceler)
deferred.addCallback(self.set_poem)
factory = PoetryClientFactory(deferred)
from twisted.internet import reactor
connector = reactor.connectTCP(self.host, self.port, factory)
return factory.deferred
def set_poem(self, poem):
self.poem = poem
return poem
def main():
options, server_addr = parse_args()
service = ProxyService(*server_addr)
factory = PoetryProxyFactory(service)
from twisted.internet import reactor
port = reactor.listenTCP(options.port or 0, factory,
interface=options.iface)
print 'Proxying %s on %s.' % (server_addr, port.getHost())
reactor.run()
if __name__ == '__main__':
main()
Jump to Line
Something went wrong with that request. Please try again.