root/devel/mod/rpc/debug/xmlrpc-debug-proxy.py

Revision 269, 3.8 kB (checked in by ben, 3 years ago)

--

Line 
1 #!/usr/bin/python
2
3 """HTTP debugging proxy
4
5 (Presumably) originally by Sam Rushing
6     http://www.nightmare.com/medusa/programming.html
7
8 Modified by Phillip Pearson <pp@myelin.co.nz>
9     http://www.myelin.co.nz/notes/xmlrpc-debug-proxy.html
10     (Changes placed in the public domain; do what you will)
11      
12
13 A very small proxy for HTTP that dumps out what it sees, so you can debug your
14 XML-RPC without having to decipher the output from a packet sniffer.
15
16 This is basically the proxy used in the Medusa asynchronous sockets tutorial
17 (available on http://www.nightmare.com/medusa/programming.html) with a minor
18 adjustment to make it flush its buffers before closing any connections.  Without
19 that it will drop off important things like </methodResponse> :)
20
21 Syntax: xmlrpc-debug-proxy.py <host> <port>
22
23 This will listen on port 8000+<port> and proxy through to <host>:<port>
24
25 e.g. 'aproxy.py localhost 80' listens on localhost:8080 and proxies through to
26      the local web server on port 80.
27      
28 To debug stuff connecting to Radio, run 'xmlrpc-debug-proxy.py localhost 5335'
29 and point your scripts at http://localhost:13335/RPC2 (instead of
30 http://localhost:5335/RPC2)
31
32 """
33
34 import asynchat
35 import asyncore
36 import socket
37 import string
38
39 class proxy_server (asyncore.dispatcher):
40
41         def __init__ (self, host, port):
42                 asyncore.dispatcher.__init__ (self)
43                 self.create_socket (socket.AF_INET, socket.SOCK_STREAM)
44                 self.set_reuse_addr()
45                 self.there = (host, port)
46                 here = ('', port + 8000)
47                 self.bind (here)
48                 self.listen (5)
49        
50         def handle_accept (self):
51                 print 'New connection'
52                 proxy_receiver (self, self.accept())
53
54 class proxy_sender (asynchat.async_chat):
55
56         "Sends data to the server"
57
58         def __init__ (self, receiver, address):
59                 asynchat.async_chat.__init__ (self)
60                 self.receiver = receiver
61                 self.set_terminator (None)
62                 self.create_socket (socket.AF_INET, socket.SOCK_STREAM)
63                 self.buffer = ''
64                 self.set_terminator ('\n')
65                 self.connect (address)
66        
67         def handle_connect (self):
68                 print 'Sender connected'
69        
70         def collect_incoming_data (self, data):
71                 self.buffer = self.buffer + data
72        
73         def found_terminator (self):
74                 data = self.buffer
75                 self.buffer = ''
76                 print '==> (%d) %s' % (self.id, repr(data))
77                 self.receiver.push (data + '\n')
78        
79         def handle_close (self):
80                 print 'Sender closing (inbuf len %d (%s), ac_in %d, ac_out %d )' % (
81                         len( self.buffer ),
82                         self.buffer,
83                         len( self.ac_in_buffer ),
84                         len( self.ac_out_buffer )
85                         )
86
87                 if len( self.buffer ):
88                         self.found_terminator()
89                        
90                 self.receiver.close_when_done()
91                 self.close()
92
93 class proxy_receiver (asynchat.async_chat):
94
95         "Receives data from the caller"
96
97         channel_counter = 0
98        
99         def __init__ (self, server, (conn, addr)):
100                 asynchat.async_chat.__init__ (self, conn)
101                 self.set_terminator ('\n')
102                 self.server = server
103                 self.id = self.channel_counter
104                 self.channel_counter = self.channel_counter + 1
105                 self.sender = proxy_sender (self, server.there)
106                 self.sender.id = self.id
107                 self.buffer = ''
108        
109         def collect_incoming_data (self, data):
110                 self.buffer = self.buffer + data
111                
112         def found_terminator (self):
113                 import re
114                 data = re.sub( r'\:8080', '', self.buffer )
115                 data = re.sub( r'localhost', self.server.there[0], data )
116                 self.buffer = ''
117                 print '<== (%d) %s' % (self.id, repr(data))
118                 self.sender.push (data + '\n')
119        
120         def handle_close (self):
121                 print 'Receiver closing (inbuf len %d (%s), ac_in %d, ac_out %d )' % (
122                         len( self.buffer ),
123                         self.buffer,
124                         len( self.ac_in_buffer ),
125                         len( self.ac_out_buffer )
126                         )
127
128                 if len( self.buffer ):
129                         self.found_terminator()
130                
131                 self.sender.close_when_done()
132                 self.close()
133
134 if __name__ == '__main__':
135         import sys
136         import string
137         if len(sys.argv) < 3:
138                 print 'Usage: %s <server-host> <server-port>' % sys.argv[0]
139         else:
140                 ps = proxy_server (sys.argv[1], string.atoi (sys.argv[2]))
141                 asyncore.loop()
Note: See TracBrowser for help on using the browser.