Hi,
While developping a non blocking HTTP client for Protocols.XMLRPC I went throught a problem with Protocols.HTTP.Session (with Pike 7.6).
Here is the testcode:
void data_ok(mixed result) { write("result=%O\n", result); }
void fail() { write("fail\n"); }
int main(int argc, array argv) { object async_client = Protocols.XMLRPC.AsyncClient("http://www.oreillynet.com/meerkat/xml-rpc/server.php"); async_client["system.listMethods"](data_ok, fail); async_client["system.listMethods"](data_ok, fail); return -1; }
The first async_client fail sometime (not always) because ->data() from the Request object returned by Protocols.HTTP.Session returned the empty string while the query is valid and the answer from the server ok.
However the second call always succeeded.
Now if I remove one call to async_client->`[] everything went fine.
The code of the class is as follow:
class AsyncClient { static object request; static function user_data_ok; static string _url;
void create(string|Standards.URI|Protocols.HTTP.Session.SessionURL url) { _url = url; }
static void _data_ok() { mixed result; // sometimes request->data() is "" even if query succeed an answer // from HTTP server is ok if(request) result = decode_response(request->data()); user_data_ok(result); }
function `[](string call) { return lambda(function data_ok, function fail, mixed ...args) { user_data_ok = data_ok; request = Protocols.HTTP.Session()->async_do_method_url( "POST", _url, 0, encode_call( call, args ), ([ "content-type":"text/xml"]), 0, _data_ok, fail, ({ })); }; } }
Example of a failed query:
<- "" <- "" <- "POST /meerkat/xml-rpc/server.php HTTP/1.1\r\nConnection: Keep-Alive\r\nContent-length: 112\r\nUser-agent: Mozilla/5.0 (compatible; MSIE 6.0; Pike HTTP client) Pike/7.6.9\r\nContent-type: text/xml\r\nHost: www.oreillynet.com\r\n\r\n<?xml version=\"1.0\"?>\n<methodCall>\n<methodName>system.listMethods</methodName>\n< params>\n</params>\n</methodCall>\n" <- "POST /meerkat/xml-rpc/server.php HTTP/1.1\r\nConnection: Keep-Alive\r\nContent-length: 112\r\nUser-agent: Mozilla/5.0 (compatible; MSIE 6.0; Pike HTTP client) Pike/7.6.9\r\nContent-type: text/xml\r\nHost: www.oreillynet.com\r\n\r\n<?xml version=\"1.0\"?>\n<methodCall>\n<methodName>system.listMethods</methodName>\n< params>\n</params>\n</methodCall>\n" -> 1101 bytes of data ** 448 bytes of header; 640 bytes left in buffer (pos=461) Attempt to index the empty array with 0. /usr/local/pike/7.6.9/lib/modules/Protocols.pmod/XMLRPC.pmod/module.pmod:267: Protocols.XMLRPC->decode("","\n<!DOCTYPE methodResponse [\n <!ELEMENT methodResponse (params|fault)>\n <!ELEMENT fault (value)>\n\n <!ELEMENT params (param*)>\n <!ELEMENT param (value)>\n\n <!ELEMENT value (#PCDA"+[534])
/usr/local/pike/7.6.9/lib/modules/Protocols.pmod/XMLRPC.pmod/module.pmod:98: Protocols.XMLRPC->decode_response("")
/usr/local/pike/7.6.9/lib/modules/Protocols.pmod/XMLRPC.pmod/module.pmod:394: Protocols.XMLRPC.AsyncClient()->_data_ok()
/usr/local/pike/7.6.9/lib/modules/Protocols.pmod/HTTP.pmod/Session.pike:317: Request("http://www.oreillynet.com/meerkat/xml-rpc/server.php" - connected - 1101 bytes received)->async_data()
/usr/local/pike/7.6.9/lib/modules/Protocols.pmod/HTTP.pmod/Query.pike:986: Protocols.HTTP.Session()->SessionQuery(200 OK)->async_fetch(Request("http: //www.oreillynet.com/meerkat/xml-rpc/server.php" - connected - 1101 bytes received)->async_data)
/usr/local/pike/7.6.9/lib/modules/Protocols.pmod/HTTP.pmod/Session.pike:295: Request("http://www.oreillynet.com/meerkat/xml-rpc/server.php" - connected - 1101 bytes received)->async_ok(Protocols.HTTP.Session()->SessionQuery(2 00 OK))
/usr/local/pike/7.6.9/lib/modules/Protocols.pmod/HTTP.pmod/Query.pike:135: Protocols.HTTP.Session()->SessionQuery(200 OK)->ponder_answer(0)
/usr/local/pike/7.6.9/lib/modules/Protocols.pmod/HTTP.pmod/Query.pike:224: Protocols.HTTP.Session()->SessionQuery(200 OK)->async_read(0,"HTTP/1.1 200 OK\r\nDate: Tue, 08 Jun 2004 15:43:22 GMT\r\nServer: Apache/1.3.29 (Unix) PHP/4.3.4 mod_perl/1.29\r\nP3P: policyref="http://www.oreillynet.com/w3c /p3p.xml",CP="CAO DSP COR CURa ADMa DEVa T"+[907])
/usr/local/pike/7.6.9/lib/modules/Stdio.pmod/module.pmod:815: Stdio.File("socket", "208.201.239.37:80", 777 /* fd=11 */)->__stdio_read_c allback()
_static_modules.Builtin()->Backend: Pike.Backend(0)->`()() -> 1120 bytes of data ** 467 bytes of header; 640 bytes left in buffer (pos=480) fetch data: 640 bytes needed, got 640, 0 left buf[datapos..] : "<?xml version="1.0"?" buf[..datapos+len] : ">\n</methodResponse>" result=({ /* 1 element */ ({ /* 9 elements */ "meerkat.getChannels", "meerkat.getCategories", "meerkat.getCategoriesBySubstring", "meerkat.getChannelsByCategory", "meerkat.getChannelsBySubstring", "meerkat.getItems", "system.listMethods", "system.methodHelp", "system.methodSignature" }) })
Also I'd like to know if there are practical examples of how to use keep-alive with Protocols.HTTP.Session and how does it work basically (especially I don't understand give_me_connection since it returns a Query object, shouldn't it returned a Request object ?).
/ David
pike-devel@lists.lysator.liu.se