Description
XMLRPC requests fail when MoinMoin is invoked via the WSGI server. These was tested with the CherryPy WSGI server and wsgiref.
Versions: Python 2.5.2, MoinMoin 1.6.3, CherryPy 3.0.3.
With CherryPy, the request times out and fails.
With wsgiref, the request hangs forever.
Testing was performing using both Python and Ruby XMLRPC clients. The results were the same in both cases.
Steps to reproduce
Create a WSGI server instance. This example uses wsgiref:
1 #!/webworks/wiki/bin/python 2 3 # Straight from the CherryPy WSGI server code docs 4 # 5 6 import os 7 import sys 8 import logging 9 import MoinMoin.server.server_wsgi 10 11 # Specify path to wiki instance 12 # 13 wiki_path = '/Users/allums/wiki.flipnotics' 14 15 # Configure MoinMoin 16 # 17 18 # MoinMoin 'wikiconfig.py' in sys.path 19 # 20 sys.path.insert(0, wiki_path) 21 22 # Initialize MoinMoin logging 23 # 24 class Config(MoinMoin.server.server_wsgi.WsgiConfig): 25 logPath = os.path.join(wiki_path, 'logs/moin.log') 26 loglevel_file = logging.INFO # None 27 loglevel_stderr = None 28 29 config = Config() # you MUST create an instance to initialize logging! 30 31 # Launch server 32 # 33 server_name = 'localhost' 34 server_host = '127.0.0.1' 35 server_port = 8080 36 37 from wsgiref.simple_server import make_server 38 39 httpd = make_server(server_host, server_port, MoinMoin.server.server_wsgi.moinmoinApp) 40 41 if __name__ == '__main__': 42 try: 43 httpd.serve_forever() 44 except KeyboardInterrupt: 45 pass
Attempt any simple XMLRPC request, such as getPage():
Example
See #2 above.
Component selection
I believe the defect is occurring in the MoinMoin WSGI application, though the thing is so simple, I don't see how that could be the case.
Details
MoinMoin Version |
1.6.3 |
OS and Version |
Mac OS X 10.4.11 |
Python Version |
2.5.2 |
Server Setup |
wsgiref and/or CherryPy WSGI server |
Server Details |
None. |
Language you are using the wiki in (set in the browser/UserPreferences) |
English |
wsgiref Server:
Request simply hangs until killed, which produces this client-side traceback.
connect: (localhost, 8080) connect fail: ('localhost', 8080) connect: (localhost, 8080) send: 'POST /?action=xmlrpc2 HTTP/1.0\r\nHost: localhost:8080\r\nUser-Agent: xmlrpclib.py/1.0.1 (by www.pythonware.com)\r\nContent-Type: text/xml\r\nContent-Length: 160\r\n\r\n' send: "<?xml version='1.0'?>\n<methodCall>\n<methodName>getPage</methodName>\n<params>\n<param>\n<value><string>FrontPage</string></value>\n</param>\n</params>\n</methodCall>\n" ^CTraceback (most recent call last): File "wsgi_debug.py", line 8, in <module> result = server.getPage("FrontPage") File "/webworks/wiki/lib/python2.5/xmlrpclib.py", line 1147, in __call__ return self.__send(self.__name, args) File "/webworks/wiki/lib/python2.5/xmlrpclib.py", line 1437, in __request verbose=self.__verbose File "/webworks/wiki/lib/python2.5/xmlrpclib.py", line 1185, in request errcode, errmsg, headers = h.getreply() File "/webworks/wiki/lib/python2.5/httplib.py", line 1199, in getreply response = self._conn.getresponse() File "/webworks/wiki/lib/python2.5/httplib.py", line 928, in getresponse response.begin() File "/webworks/wiki/lib/python2.5/httplib.py", line 385, in begin version, status, reason = self._read_status() File "/webworks/wiki/lib/python2.5/httplib.py", line 343, in _read_status line = self.fp.readline() File "/webworks/wiki/lib/python2.5/socket.py", line 331, in readline data = recv(1) KeyboardInterrupt
CherryPy Server:
This traceback occurs after a timeout of 30 seconds.
connect: (localhost, 8080) connect fail: ('localhost', 8080) connect: (localhost, 8080) send: 'POST /?action=xmlrpc2 HTTP/1.0\r\nHost: localhost:8080\r\nUser-Agent: xmlrpclib.py/1.0.1 (by www.pythonware.com)\r\nContent-Type: text/xml\r\nContent-Length: 160\r\n\r\n' send: "<?xml version='1.0'?>\n<methodCall>\n<methodName>getPage</methodName>\n<params>\n<param>\n<value><string>FrontPage</string></value>\n</param>\n</params>\n</methodCall>\n" reply: 'HTTP/1.1 200 OK\r\n' header: Content-Type: text/xml; charset=utf-8 header: Content-Length: 678 header: Date: Fri, 06 Jun 2008 18:58:19 GMT header: Server: CherryPy/3.0.3 body: '<?xml version=\'1.0\'?>\n<methodResponse>\n<fault>\n<value><struct>\n<member>\n<name>faultCode</name>\n<value><int>1</int></value>\n</member>\n<member>\n<name>faultString</name>\n<value><string><class \'socket.timeout\'>: timed out\n File "/webworks/wiki/lib/python2.5/site-packages/MoinMoin/xmlrpc/__init__.py", line 122, in process\n data = self.request.read()\n\n File "/webworks/wiki/lib/python2.5/site-packages/MoinMoin/request/request_wsgi.py", line 49, in read\n read_data = self.stdin.read(4000)\n\n File "/webworks/wiki/lib/python2.5/socket.py", line 309, in read\n data = self._sock.recv(recv_size)\n</string></value>\n</member>\n</struct></value>\n</fault>\n</methodResponse>\n' Traceback (most recent call last): File "wsgi_debug.py", line 8, in <module> result = server.getPage("FrontPage") File "/webworks/wiki/lib/python2.5/xmlrpclib.py", line 1147, in __call__ return self.__send(self.__name, args) File "/webworks/wiki/lib/python2.5/xmlrpclib.py", line 1437, in __request verbose=self.__verbose File "/webworks/wiki/lib/python2.5/xmlrpclib.py", line 1201, in request return self._parse_response(h.getfile(), sock) File "/webworks/wiki/lib/python2.5/xmlrpclib.py", line 1340, in _parse_response return u.close() File "/webworks/wiki/lib/python2.5/xmlrpclib.py", line 787, in close raise Fault(**self._stack[0]) xmlrpclib.Fault: <Fault 1: '<class \'socket.timeout\'>: timed out\n File "/webworks/wiki/lib/python2.5/site-packages/MoinMoin/xmlrpc/__init__.py", line 122, in process\n data = self.request.read()\n\n File "/webworks/wiki/lib/python2.5/site-packages/MoinMoin/request/request_wsgi.py", line 49, in read\n read_data = self.stdin.read(4000)\n\n File "/webworks/wiki/lib/python2.5/socket.py", line 309, in read\n data = self._sock.recv(recv_size)\n'>
Workaround
Run MoinMoin in standalone server mode to avoid having to build/configure Apache.
Discussion
Maybe try out a newer Python Version? MoinMoin needs Python 2.3 or higher (we recommend using Python 2.4.x or 2.5.x if possible).
Possible generic code changes for all Request.read() methods per ThomasWaldmann:
1 def read(self, n=None): 2 data = [] 3 4 # Read length provided? 5 if n is None: 6 # Try content length 7 try: 8 n = int(self.headers.get('content-length')) 9 except (TypeError, ValueError): 10 pass 11 12 # Still no read length provided? 13 if n is None: 14 # We can't do that, because wsgi 1.0 requires n: 15 #return self.stdin.read() 16 # Thus, if we have no n, we have to simulate the usual behaviour (or 17 # it won't work e.g. with mod_wsgi 1.3 and maybe other wsgi 1.0 servers). 18 # Note: just requesting a extremely large amount (expecting it to never 19 # be reached, but still all data returned) also does not work (mod_wsgi 20 # 1.3 gives a MemoryError when doing that): 21 while True: 22 read_data = self.stdin.read(4000) 23 if not read_data: 24 break 25 data.append(read_data) 26 else: 27 n_remaining = n 28 while n_remaining > 0: 29 if (n_remaining > 4000): 30 n_chunk = 4000 31 n_remaining -= n_chunk 32 else: 33 n_chunk = n_remaining 34 n_remaining = 0 35 read_data = self.stdin.read(n_chunk) 36 if not read_data: 37 break; 38 data.append(read_data) 39 40 return ''.join(data)
Plan
- Priority:
- Assigned to:
Status: fixed by http://hg.moinmo.in/moin/1.6/rev/8adefd81aac5 and http://hg.moinmo.in/moin/1.7/rev/fee546fba271