You can subscribe to this list here.
2003 |
Jan
|
Feb
(27) |
Mar
(132) |
Apr
(63) |
May
(100) |
Jun
(22) |
Jul
(7) |
Aug
(3) |
Sep
(14) |
Oct
(24) |
Nov
(49) |
Dec
(17) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2004 |
Jan
(13) |
Feb
(43) |
Mar
(67) |
Apr
(21) |
May
(24) |
Jun
(3) |
Jul
(15) |
Aug
|
Sep
(1) |
Oct
(40) |
Nov
(2) |
Dec
(94) |
2005 |
Jan
(5) |
Feb
(36) |
Mar
(10) |
Apr
(8) |
May
(35) |
Jun
(13) |
Jul
(55) |
Aug
(82) |
Sep
(59) |
Oct
(20) |
Nov
(55) |
Dec
(15) |
2006 |
Jan
(40) |
Feb
(25) |
Mar
(42) |
Apr
(1) |
May
(12) |
Jun
(3) |
Jul
(2) |
Aug
(23) |
Sep
(33) |
Oct
(4) |
Nov
(5) |
Dec
(22) |
2007 |
Jan
(10) |
Feb
|
Mar
(4) |
Apr
(3) |
May
(8) |
Jun
(4) |
Jul
|
Aug
(3) |
Sep
(12) |
Oct
(9) |
Nov
(1) |
Dec
|
2008 |
Jan
|
Feb
(5) |
Mar
(4) |
Apr
|
May
(4) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(7) |
Nov
|
Dec
|
2009 |
Jan
(8) |
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(11) |
Aug
|
Sep
(3) |
Oct
|
Nov
|
Dec
|
2011 |
Jan
(7) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Serge A. <as...@us...> - 2009-01-31 00:18:21
|
Update of /cvsroot/jungerl/jungerl/lib/otp.net/OtpTest In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv8581/OtpTest Added Files: OtpTest.csproj Test.cs Log Message: Version 0.5 --- NEW FILE: Test.cs --- using System; namespace Otp { public class Test { static public void Main(String[] args) { System.Console.Out.WriteLine("Otp test..."); if (args.Length < 1) { System.Console.Out.WriteLine("Usage: Otp sname\n where sname is" + "the short name of the Erlang node"); return; } OtpNode.useShortNames = true; String host = System.Net.Dns.GetHostName(); String user = Environment.UserName; OtpNode node = new OtpNode(user + "@" + host); String remote = (args[0].Contains("@")) ? args[0] : remote = args[0] + "@" + host; OtpMbox mbox = null; System.Console.Out.WriteLine("This node is: {0} (cookie='{1}'). Remote: {2}", node.node(), node.cookie(), remote); //bool ok = node.ping(remote, 1000*300); OtpCookedConnection conn = node.getConnection(remote); try { if (conn != null) System.Console.Out.WriteLine(" successfully pinged node " + remote + "\n"); else throw new System.Exception("Could not ping node: " + remote); conn.traceLevel = 1; mbox = node.createMbox(); mbox.registerName("server"); mbox.sendRPC(conn.peer.node(), "lists", "reverse", new Erlang.List(new Erlang.String("Hello world!"))); Erlang.Object reply = mbox.receiveRPC(5000); System.Console.Out.WriteLine("<= " + reply.ToString()); { Erlang.List rpcArgs = new Erlang.List( new Erlang.Object[] { mbox.self(), new Erlang.Tuple( new Erlang.Object[] { new Erlang.Atom("table"), new Erlang.Atom("test"), new Erlang.Atom("simple") } ) } ); mbox.sendRPC(conn.peer.node(), "mnesia_subscr", "subscribe", rpcArgs); reply = mbox.receiveRPC(5000); System.Console.Out.WriteLine("<= " + reply.ToString()); } while (true) { Erlang.Object msg = mbox.receive(); System.Console.Out.WriteLine("IN msg: " + msg.ToString() + "\n"); } } catch (System.Exception e) { System.Console.Out.WriteLine("Error: " + e.ToString()); } finally { node.closeMbox(mbox); } node.close(); } } } --- NEW FILE: OtpTest.csproj --- (This appears to be a binary file; contents omitted.) |
From: Serge A. <as...@us...> - 2009-01-31 00:18:21
|
Update of /cvsroot/jungerl/jungerl/lib/otp.net/OtpTest1 In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv8581/OtpTest1 Added Files: OtpTest1.2008.csproj OtpTest1.csproj Test1.cs Log Message: Version 0.5 --- NEW FILE: Test1.cs --- (This appears to be a binary file; contents omitted.) --- NEW FILE: OtpTest1.2008.csproj --- (This appears to be a binary file; contents omitted.) --- NEW FILE: OtpTest1.csproj --- (This appears to be a binary file; contents omitted.) |
From: Serge A. <as...@us...> - 2009-01-31 00:14:57
|
Update of /cvsroot/jungerl/jungerl/lib/otp.net/OtpTest/Properties In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv8394/OtpTest/Properties Log Message: Directory /cvsroot/jungerl/jungerl/lib/otp.net/OtpTest/Properties added to the repository |
From: Serge A. <as...@us...> - 2009-01-31 00:14:16
|
Update of /cvsroot/jungerl/jungerl/lib/otp.net/OtpTest1 In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv8360/OtpTest1 Log Message: Directory /cvsroot/jungerl/jungerl/lib/otp.net/OtpTest1 added to the repository |
From: Serge A. <as...@us...> - 2009-01-31 00:14:15
|
Update of /cvsroot/jungerl/jungerl/lib/otp.net/OtpTest In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv8360/OtpTest Log Message: Directory /cvsroot/jungerl/jungerl/lib/otp.net/OtpTest added to the repository |
From: Richard C. <ric...@us...> - 2008-10-24 13:58:57
|
Update of /cvsroot/jungerl/jungerl/lib/xmlrpc/src In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv25839/src Modified Files: xmlrpc.erl Log Message: applied patch by magnus at Kreditor, originally dated 2007-02-06: bug fix for listening on specific IP address Index: xmlrpc.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/xmlrpc/src/xmlrpc.erl,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- xmlrpc.erl 5 Dec 2006 14:43:42 -0000 1.4 +++ xmlrpc.erl 24 Oct 2008 13:58:46 -0000 1.5 @@ -256,7 +256,7 @@ tcp_serv:start_link([Port, MaxSessions, OptionList, SessionHandler]). ip(all) -> []; -ip(IP) when tuple(IP) -> {ip, IP}. +ip(IP) when tuple(IP) -> [{ip, IP}]. %% Exported: stop/1 |
From: Richard C. <ric...@us...> - 2008-10-24 13:33:31
|
Update of /cvsroot/jungerl/jungerl/lib/xmlrpc/src In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv24460/src Modified Files: xmlrpc_encode.erl Log Message: applied patch by happi at Kreditor, originally dated 2006-02-22 Index: xmlrpc_encode.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/xmlrpc/src/xmlrpc_encode.erl,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- xmlrpc_encode.erl 24 Oct 2008 13:05:46 -0000 1.4 +++ xmlrpc_encode.erl 24 Oct 2008 13:33:27 -0000 1.5 @@ -35,7 +35,7 @@ {error, Reason} -> {error, Reason}; EncodedParams -> EncodedPayload = - ["<?xml version=\"1.0\" encoding=\"iso_8859-1\"?><methodCall><methodName>", + ["<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><methodCall><methodName>", atom_to_list(Name), "</methodName>", EncodedParams, "</methodCall>"], {ok, EncodedPayload} @@ -44,7 +44,7 @@ case xmlrpc_util:is_string(String) of yes -> EncodedPayload = - ["<?xml version=\"1.0\" encoding=\"iso_8859-1\"?><methodResponse><fault>" + ["<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><methodResponse><fault>" "<value><struct><member><name>faultCode</name><value><int>", integer_to_list(Code), "</int></value></member><member><name>" "faultString</name><value><string>", escape_string(String), @@ -59,7 +59,7 @@ case encode_params([Param]) of {error, Reason} -> {error, Reason}; EncodedParam -> - {ok, ["<?xml version=\"1.0\"?><methodResponse>", EncodedParam, + {ok, ["<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><methodResponse>", EncodedParam, "</methodResponse>"]} end; payload(Payload) -> {error, {bad_payload, Payload}}. @@ -98,7 +98,7 @@ ["<base64>", Base64, "</base64>"]; encode(Value) -> case xmlrpc_util:is_string(Value) of - yes -> escape_string(Value); + yes -> ["<string>", escape_string(Value), "</string>"]; no -> {error, {bad_value, Value}} end. |
From: Richard C. <ric...@us...> - 2008-10-24 13:24:52
|
Update of /cvsroot/jungerl/jungerl/lib/xmlrpc/src In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv23969/src Modified Files: xmlrpc_decode.erl Log Message: applied patch from unknown person at Kreditor, originally dated 2005-04-04, to handle 'doubles' without decimal point Index: xmlrpc_decode.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/xmlrpc/src/xmlrpc_decode.erl,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- xmlrpc_decode.erl 24 Oct 2008 13:01:52 -0000 1.2 +++ xmlrpc_decode.erl 24 Oct 2008 13:24:40 -0000 1.3 @@ -195,7 +195,12 @@ make_double(Double) -> case catch list_to_float(Double) of - {'EXIT', _} -> throw({error, {not_double, Double}}); + {'EXIT', _} -> + case catch list_to_integer(Double) of + {'EXIT', _} -> + throw({error, {not_double, Double}}); + Value -> float(Value) + end; Value -> Value end. |
From: Richard C. <ric...@us...> - 2008-10-24 13:05:53
|
Update of /cvsroot/jungerl/jungerl/lib/xmlrpc/src In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv22490/src Modified Files: xmlrpc_encode.erl Log Message: applied patch by jocke, originally dated 2005-02-02 Index: xmlrpc_encode.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/xmlrpc/src/xmlrpc_encode.erl,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- xmlrpc_encode.erl 24 Oct 2008 13:01:52 -0000 1.3 +++ xmlrpc_encode.erl 24 Oct 2008 13:05:46 -0000 1.4 @@ -35,7 +35,7 @@ {error, Reason} -> {error, Reason}; EncodedParams -> EncodedPayload = - ["<?xml version=\"1.0\"?><methodCall><methodName>", + ["<?xml version=\"1.0\" encoding=\"iso_8859-1\"?><methodCall><methodName>", atom_to_list(Name), "</methodName>", EncodedParams, "</methodCall>"], {ok, EncodedPayload} @@ -44,7 +44,7 @@ case xmlrpc_util:is_string(String) of yes -> EncodedPayload = - ["<?xml version=\"1.0\"?><methodResponse><fault>" + ["<?xml version=\"1.0\" encoding=\"iso_8859-1\"?><methodResponse><fault>" "<value><struct><member><name>faultCode</name><value><int>", integer_to_list(Code), "</int></value></member><member><name>" "faultString</name><value><string>", escape_string(String), |
From: Richard C. <ric...@us...> - 2008-10-24 13:02:04
|
Update of /cvsroot/jungerl/jungerl/lib/xmlrpc/test In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv22156/test Modified Files: test.erl Log Message: applied patch by jocke, originally dated 2005-01-31 Index: test.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/xmlrpc/test/test.erl,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- test.erl 25 Feb 2003 20:10:58 -0000 1.2 +++ test.erl 24 Oct 2008 13:01:52 -0000 1.3 @@ -1,7 +1,7 @@ -module(test). -compile(export_all). --include("../../xmerl/inc/xmerl.hrl"). +-include_lib("xmerl/include/xmerl.hrl"). all() -> t10(), @@ -28,8 +28,8 @@ xmlrpc:call("localhost", 4567, "/", {call, baz, []}), xmlrpc:stop(Pid). -h10(State, {call, echo, Params}) -> {false, {response, [{array, Params}]}}; -h10(State, Payload) -> +h10(_State, {call, echo, Params}) -> {false, {response, [{array, Params}]}}; +h10(_State, Payload) -> FaultString = lists:flatten(io_lib:format("~p", [Payload])), {false, {response, {fault, -1, FaultString}}}. @@ -45,7 +45,7 @@ {error, Socket, closed} = xmlrpc:call(Socket, "/", Payload, true, 60000), xmlrpc:stop(Pid). -h20(State, {call, echo, Params}) -> {false, {response, [{array, Params}]}}. +h20(_State, {call, echo, Params}) -> {false, {response, [{array, Params}]}}. %% Test: Keep-Alive handler <-> Non keep-alive client @@ -94,7 +94,7 @@ xmlrpc:call(Socket2, "/", Payload, true, 60000), xmlrpc:stop(Pid). -h40(N, {call, close, []}) -> {false, {response, ["ok"]}}; +h40(_N, {call, close, []}) -> {false, {response, ["ok"]}}; h40(N, {call, echo, Params}) -> {true, 60000, N+1, {response, [{array, [N|Params]}]}}; h40(N, Payload) -> @@ -110,8 +110,8 @@ "[[42, foo], {bar=45.5, baz=4711}]\norg.apache.xmlrpc.XmlRpcException: Unknown call: {call,foo,[]}\n" = os:cmd(Cmd), xmlrpc:stop(Pid). -h50(State, {call, echo, Params}) -> {false, {response, [{array, Params}]}}; -h50(State, Payload) -> +h50(_State, {call, echo, Params}) -> {false, {response, [{array, Params}]}}; +h50(_State, Payload) -> FaultString = lists:flatten(io_lib:format("Unknown call: ~p", [Payload])), {false, {response, {fault, -1, FaultString}}}. @@ -127,7 +127,7 @@ h60(N, {call, echo, Params}) -> {true, 60000, N+1, {response, [{array, [N|Params]}]}}; -h60(N, Payload) -> +h60(_N, Payload) -> FaultString = lists:flatten(io_lib:format("Unknown call: ~p", [Payload])), {false, {response, {fault, -1, FaultString}}}. |
From: Richard C. <ric...@us...> - 2008-10-24 13:02:02
|
Update of /cvsroot/jungerl/jungerl/lib/xmlrpc/examples In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv22156/examples Modified Files: Makefile date_server.erl Log Message: applied patch by jocke, originally dated 2005-01-31 Index: Makefile =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/xmlrpc/examples/Makefile,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- Makefile 25 Feb 2003 19:59:13 -0000 1.2 +++ Makefile 24 Oct 2008 13:01:52 -0000 1.3 @@ -1,7 +1,7 @@ # Update the APACHE_XMLRPC_PATH variable to point at your Apache # XML-RPC installation. This is only necessary if you intend to # compile the Java clients. -APACHE_XMLRPC_PATH=../../apache/xmlrpc/bin/xmlrpc-1.1.jar +APACHE_XMLRPC_PATH=../test/xmlrpc-1.1.jar # Do not change anything below this line. ERLC=erlc Index: date_server.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/xmlrpc/examples/date_server.erl,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- date_server.erl 21 Feb 2003 22:29:29 -0000 1.1 +++ date_server.erl 24 Oct 2008 13:01:52 -0000 1.2 @@ -16,17 +16,17 @@ handler({false, N}, {call, login, ["Slarti", "Bartfast"]}) -> {true, infinity, {true, N+1}, {response, ["ok"]}}; -handler({false, N}, {call, login, [_, _]}) -> +handler({false, _N}, {call, login, [_, _]}) -> {false, {response, {fault, -1, "Invalid authentication"}}}; handler({true, N}, {call, login, [_, _]}) -> {true, infinity, {true, N+1}, {response, {fault, -2, "Already authenticated"}}}; -handler({true, N}, {call, logout, []}) -> +handler({true, _N}, {call, logout, []}) -> {false, {response, ["ok"]}}; handler({true, N}, {call, calc, [{struct, Elements}]}) -> {true, infinity, {true, N+1}, {response, [{array, [N, {struct, calc(Elements)}]}]}}; -handler({false, N}, {call, calc, Params}) -> +handler({false, _N}, {call, calc, _Params}) -> {false, {response, {fault, -3, "Not authenticated"}}}; handler({Status, N}, Payload) -> FaultString = lists:flatten(io_lib:format("Unknown call: ~p", [Payload])), |
From: Richard C. <ric...@us...> - 2008-10-24 13:01:58
|
Update of /cvsroot/jungerl/jungerl/lib/xmlrpc/src In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv22156/src Modified Files: tcp_serv.erl xmlrpc_decode.erl xmlrpc_encode.erl Log Message: applied patch by jocke, originally dated 2005-01-31 Index: tcp_serv.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/xmlrpc/src/tcp_serv.erl,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- tcp_serv.erl 28 Apr 2003 20:26:18 -0000 1.3 +++ tcp_serv.erl 24 Oct 2008 13:01:52 -0000 1.4 @@ -139,7 +139,7 @@ ?ERROR_LOG({M, F, Reason}), gen_tcp:close(Socket) end; - {error, Reason} -> + {error, _Reason} -> timer:sleep(5000), Parent ! start_session end. @@ -151,6 +151,6 @@ %% Exported: system_terminate/3 -system_terminate(Reason, Parent, DebugInfo, State) -> +system_terminate(Reason, _Parent, _DebugInfo, State) -> cleanup(State), exit(Reason). Index: xmlrpc_encode.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/xmlrpc/src/xmlrpc_encode.erl,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- xmlrpc_encode.erl 25 Feb 2003 19:59:18 -0000 1.2 +++ xmlrpc_encode.erl 24 Oct 2008 13:01:52 -0000 1.3 @@ -53,9 +53,9 @@ {ok, EncodedPayload}; no -> {error, {bad_string, String}} end; -payload({response, []} = Payload) -> +payload({response, []}) -> {ok, ["<?xml version=\"1.0\"?><methodResponse></methodResponse>"]}; -payload({response, [Param]} = Payload) -> +payload({response, [Param]}) -> case encode_params([Param]) of {error, Reason} -> {error, Reason}; EncodedParam -> @@ -93,15 +93,9 @@ encode(Double) when float(Double) -> ["<double>", io_lib:format("~p", [Double]), "</double>"]; encode({date, Date}) -> - case xmlrpc_util:is_iso8601_date(Date) of - yes -> ["<dateTime.iso8601>", Date, "</dateTime.iso8601>"]; - no -> {error, {bad_date, Date}} - end; + ["<dateTime.iso8601>", Date, "</dateTime.iso8601>"]; encode({base64, Base64}) -> - case xmlrpc_util:is_base64(Base64) of - yes -> ["<base64>", Base64, "</base64>"]; - no -> {error, {bad_base64, Base64}} - end; + ["<base64>", Base64, "</base64>"]; encode(Value) -> case xmlrpc_util:is_string(Value) of yes -> escape_string(Value); @@ -126,8 +120,8 @@ EncodedValue, "</value></member>"], encode_members(Rest, NewAcc) end; -encode_members([{Name, Value}|Rest], Acc) -> {error, {invalid_name, Name}}; -encode_members(UnknownMember, Acc) -> +encode_members([{Name, _Value}|_Rest], _Acc) -> {error, {invalid_name, Name}}; +encode_members(UnknownMember, _Acc) -> {error, {unknown_member, UnknownMember}}. encode_values(Array) -> encode_values(Array, []). @@ -140,6 +134,5 @@ NewAcc = Acc++["<value>", EncodedValue, "</value>"], encode_values(Rest, NewAcc) end; -encode_values([{Name, Value}|Rest], Acc) -> {error, {invalid_name, Name}}; -encode_values(UnknownMember, Acc) -> +encode_values(UnknownMember, _Acc) -> {error, {unknown_member, UnknownMember}}. Index: xmlrpc_decode.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/xmlrpc/src/xmlrpc_decode.erl,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- xmlrpc_decode.erl 21 Feb 2003 22:29:29 -0000 1.1 +++ xmlrpc_decode.erl 24 Oct 2008 13:01:52 -0000 1.2 @@ -28,16 +28,17 @@ -author('jo...@gl...'). -export([payload/1]). --include("xmerl.hrl"). +-include("log.hrl"). +-include_lib("xmerl/include/xmerl.hrl"). payload(Payload) -> - case xmerl_scan:string(Payload) of + case catch xmerl_scan:string(Payload) of + {'EXIT', Reason} -> {error, Reason}; {E, _} -> case catch decode_element(E) of - {'EXIT', Reason} -> exit(Reason); + {'EXIT', Reason} -> {error, Reason}; Result -> Result - end; - {error, Reason} -> {error, Reason} + end end. decode_element(#xmlElement{name = methodCall} = MethodCall) @@ -141,10 +142,12 @@ make_double(TextValue); decode(Date) when Date#xmlElement.name == 'dateTime.iso8601' -> TextValue = get_text_value(Date#xmlElement.content), - {date, ensure_iso8601_date(TextValue)}; +% {date, ensure_iso8601_date(TextValue)}; % FIXME + {date, TextValue}; decode(Base64) when Base64#xmlElement.name == base64 -> TextValue = get_text_value(Base64#xmlElement.content), - {base64, ensure_base64(TextValue)}; +% {base64, ensure_base64(TextValue)}; % FIXME + {base64, TextValue}; decode(Value) -> throw({error, {bad_value, Value}}). get_value(Content) -> @@ -186,7 +189,7 @@ make_integer(Integer) -> case catch list_to_integer(Integer) of - {'EXIT', Reason} -> throw({error, {not_integer, Integer}}); + {'EXIT', _Reason} -> throw({error, {not_integer, Integer}}); Value -> Value end. @@ -196,14 +199,15 @@ Value -> Value end. -ensure_iso8601_date(Date) -> - case xmlrpc_util:is_iso8601_date(Date) of - no -> throw({error, {not_iso8601_date, Date}}); - yes -> Date - end. - -ensure_base64(Base64) -> - case xmlrpc_util:is_base64(Base64) of - no -> throw({error, {not_base64, Base64}}); - yes -> Base64 - end. +% FIXME +%ensure_iso8601_date(Date) -> +% case xmlrpc_util:is_iso8601_date(Date) of +% no -> throw({error, {not_iso8601_date, Date}}); +% yes -> Date +% end. +% +%ensure_base64(Base64) -> +% case xmlrpc_util:is_base64(Base64) of +% no -> throw({error, {not_base64, Base64}}); +% yes -> Base64 +% end. |
From: Chandru <cha...@us...> - 2008-05-21 22:06:52
|
Update of /cvsroot/jungerl/jungerl/lib/ibrowse/src In directory sc8-pr-cvs17.sourceforge.net:/tmp/cvs-serv16700/src Modified Files: ibrowse.erl ibrowse_http_client.erl ibrowse_test.erl Log Message: ibrowse was not reading all the options from its config file. Index: ibrowse.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ibrowse/src/ibrowse.erl,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- ibrowse.erl 27 Mar 2008 01:35:50 -0000 1.6 +++ ibrowse.erl 21 May 2008 15:28:11 -0000 1.7 @@ -239,10 +239,11 @@ end, Max_sessions = get_max_sessions(Host, Port, Options), Max_pipeline_size = get_max_pipeline_size(Host, Port, Options), + Options_1 = merge_options(Host, Port, Options), {SSLOptions, IsSSL} = - case get_value(is_ssl, Options, false) of + case get_value(is_ssl, Options_1, false) of false -> {[], false}; - true -> {get_value(ssl_options, Options), true} + true -> {get_value(ssl_options, Options_1), true} end, case ibrowse_lb:spawn_connection(Lb_pid, Parsed_url, Max_sessions, @@ -250,7 +251,7 @@ {SSLOptions, IsSSL}) of {ok, Conn_Pid} -> do_send_req(Conn_Pid, Parsed_url, Headers, - Method, Body, Options, Timeout); + Method, Body, Options_1, Timeout); Err -> Err end; @@ -258,6 +259,18 @@ {error, {url_parsing_failed, Err}} end. +merge_options(Host, Port, Options) -> + Config_options = get_config_value({options, Host, Port}, []), + lists:foldl( + fun({Key, Val}, Acc) -> + case lists:keysearch(Key, 1, Options) of + false -> + [{Key, Val} | Acc]; + _ -> + Acc + end + end, Options, Config_options). + get_lb_pid(Url) -> gen_server:call(?MODULE, {get_lb_pid, Url}). @@ -354,8 +367,10 @@ %% returned by spawn_worker_process/2 or spawn_link_worker_process/2 send_req_direct(Conn_pid, Url, Headers, Method, Body, Options, Timeout) -> case catch parse_url(Url) of - #url{} = Parsed_url -> - case do_send_req(Conn_pid, Parsed_url, Headers, Method, Body, Options, Timeout) of + #url{host = Host, + port = Port} = Parsed_url -> + Options_1 = merge_options(Host, Port, Options), + case do_send_req(Conn_pid, Parsed_url, Headers, Method, Body, Options_1, Timeout) of {error, {'EXIT', {noproc, _}}} -> {error, worker_is_dead}; Ret -> Index: ibrowse_http_client.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ibrowse/src/ibrowse_http_client.erl,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- ibrowse_http_client.erl 27 Mar 2008 01:35:50 -0000 1.17 +++ ibrowse_http_client.erl 21 May 2008 15:28:11 -0000 1.18 @@ -1294,7 +1294,7 @@ ok; shutting_down(#state{lb_ets_tid = Tid, cur_pipeline_size = Sz}) -> - ets:delete(Tid, {Sz, self()}). + catch ets:delete(Tid, {Sz, self()}). inc_pipeline_counter(#state{is_closing = true} = State) -> State; Index: ibrowse_test.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ibrowse/src/ibrowse_test.erl,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- ibrowse_test.erl 27 Mar 2008 01:35:50 -0000 1.2 +++ ibrowse_test.erl 21 May 2008 15:28:11 -0000 1.3 @@ -32,6 +32,7 @@ Start_time = now(), ets:new(pid_table, [named_table, public]), ets:new(ibrowse_test_results, [named_table, public]), + ets:new(ibrowse_errors, [named_table, public, ordered_set]), init_results(), process_flag(trap_exit, true), log_msg("Starting spawning of workers...~n", []), @@ -45,15 +46,20 @@ log_msg("End time : ~1000.p~n", [calendar:now_to_local_time(End_time)]), Elapsed_time_secs = trunc(timer:now_diff(End_time, Start_time) / 1000000), log_msg("Elapsed : ~p~n", [Elapsed_time_secs]), - log_msg("Reqs/sec : ~p~n", [(NumWorkers*NumReqsPerWorker) / Elapsed_time_secs]). + log_msg("Reqs/sec : ~p~n", [(NumWorkers*NumReqsPerWorker) / Elapsed_time_secs]), + dump_errors(). init_results() -> ets:insert(ibrowse_test_results, {crash, 0}), ets:insert(ibrowse_test_results, {send_failed, 0}), ets:insert(ibrowse_test_results, {other_error, 0}), ets:insert(ibrowse_test_results, {success, 0}), + ets:insert(ibrowse_test_results, {retry_later, 0}), + ets:insert(ibrowse_test_results, {trid_mismatch, 0}), + ets:insert(ibrowse_test_results, {success_no_trid, 0}), ets:insert(ibrowse_test_results, {failed, 0}), - ets:insert(ibrowse_test_results, {timeout, 0}). + ets:insert(ibrowse_test_results, {timeout, 0}), + ets:insert(ibrowse_test_results, {req_id, 0}). spawn_workers(_Url, 0, _) -> ok; @@ -89,19 +95,54 @@ do_send_req_1(_Url, 0) -> ets:delete(pid_table, self()); do_send_req_1(Url, NumReqs) -> - case ibrowse:send_req(Url, [], get, [], [], 10000) of - {ok, _Status, _Headers, _Body} -> - ets:update_counter(ibrowse_test_results, success, 1); + Counter = integer_to_list(ets:update_counter(ibrowse_test_results, req_id, 1)), + case ibrowse:send_req(Url, [{"ib_req_id", Counter}], get, [], [], 10000) of + {ok, _Status, Headers, _Body} -> + case lists:keysearch("ib_req_id", 1, Headers) of + {value, {_, Counter}} -> + ets:update_counter(ibrowse_test_results, success, 1); + {value, _} -> + ets:update_counter(ibrowse_test_results, trid_mismatch, 1); + false -> + ets:update_counter(ibrowse_test_results, success_no_trid, 1) + end; {error, req_timedout} -> ets:update_counter(ibrowse_test_results, timeout, 1); {error, send_failed} -> ets:update_counter(ibrowse_test_results, send_failed, 1); - _Err -> + {error, retry_later} -> + ets:update_counter(ibrowse_test_results, retry_later, 1); + Err -> + ets:insert(ibrowse_errors, {now(), Err}), ets:update_counter(ibrowse_test_results, other_error, 1), ok end, do_send_req_1(Url, NumReqs-1). +dump_errors() -> + case ets:info(ibrowse_errors, size) of + 0 -> + ok; + _ -> + {A, B, C} = now(), + Filename = lists:flatten( + io_lib:format("ibrowse_errors_~p_~p_~p.txt" , [A, B, C])), + case file:open(Filename, [write, delayed_write, raw]) of + {ok, Iod} -> + dump_errors(ets:first(ibrowse_errors), Iod); + Err -> + io:format("failed to create file ~s. Reason: ~p~n", [Filename, Err]), + ok + end + end. + +dump_errors('$end_of_table', Iod) -> + file:close(Iod); +dump_errors(Key, Iod) -> + [{_, Term}] = ets:lookup(ibrowse_errors, Key), + file:write(Iod, io_lib:format("~p~n", [Term])), + dump_errors(ets:next(ibrowse_errors, Key), Iod). + %%------------------------------------------------------------------------------ %% Unit Tests %%------------------------------------------------------------------------------ |
From: Chandru <cha...@us...> - 2008-05-21 20:34:22
|
Update of /cvsroot/jungerl/jungerl/lib/ibrowse In directory sc8-pr-cvs17.sourceforge.net:/tmp/cvs-serv16700 Modified Files: README vsn.mk Log Message: ibrowse was not reading all the options from its config file. Index: README =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ibrowse/README,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- README 27 Mar 2008 01:35:49 -0000 1.15 +++ README 21 May 2008 15:28:11 -0000 1.16 @@ -22,6 +22,10 @@ CONTRIBUTIONS & CHANGE HISTORY ============================== +21-05-2008 - * Fixed bug in reading some options from the ibrowse.conf file. + Reported by Erik Reitsma on the erlyaws mailing list + * Fixed bug when cleaning up closing connections + 27-03-2008 - * Major rewrite of the load balancing feature. Additional module, ibrowse_lb.erl, introduced to achieve this. * Can now get a handle to a connection process which is not part of Index: vsn.mk =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ibrowse/vsn.mk,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- vsn.mk 27 Mar 2008 01:35:49 -0000 1.13 +++ vsn.mk 21 May 2008 15:28:11 -0000 1.14 @@ -1,2 +1,2 @@ -IBROWSE_VSN = 1.4 +IBROWSE_VSN = 1.4.1 |
From: Chandru <cha...@us...> - 2008-05-21 20:24:53
|
Update of /cvsroot/jungerl/jungerl/lib/ibrowse/priv In directory sc8-pr-cvs17.sourceforge.net:/tmp/cvs-serv16700/priv Modified Files: ibrowse.conf Log Message: ibrowse was not reading all the options from its config file. Index: ibrowse.conf =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ibrowse/priv/ibrowse.conf,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- ibrowse.conf 5 May 2005 22:28:28 -0000 1.1 +++ ibrowse.conf 21 May 2008 15:28:11 -0000 1.2 @@ -15,3 +15,4 @@ %% If SSL is to be used, both the options, is_ssl and ssl_options MUST be specified %% where option() is all options supported in the ssl module +{{options, "www.google.co.uk", 80}, [{proxy_host, "proxy"}, {proxy_port, 8080}, {proxy_user, "cmullaparthi"}, {proxy_password, "20nov99"}]}. |
From: Chandru <cha...@us...> - 2008-05-21 15:28:28
|
Update of /cvsroot/jungerl/jungerl/lib/ibrowse/doc In directory sc8-pr-cvs17.sourceforge.net:/tmp/cvs-serv16700/doc Modified Files: ibrowse.html Log Message: ibrowse was not reading all the options from its config file. Index: ibrowse.html =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ibrowse/doc/ibrowse.html,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- ibrowse.html 27 Mar 2008 01:35:49 -0000 1.6 +++ ibrowse.html 21 May 2008 15:28:11 -0000 1.7 @@ -181,10 +181,13 @@ <h3 class="function"><a name="send_req-4">send_req/4</a></h3> <div class="spec"> <p><tt>send_req(Url, Headers, Method::<a href="#type-method">method()</a>, Body::<a href="#type-body">body()</a>) -> <a href="#type-response">response()</a></tt> -<ul class="definitions"><li><tt><a name="type-body">body()</a> = [] | string() | binary()</tt></li> +<ul class="definitions"><li><tt><a name="type-body">body()</a> = [] | string() | binary() | <a href="#type-fun_arity_0">fun_arity_0()</a> | {<a href="#type-fun_arity_1">fun_arity_1()</a>, <a href="#type-initial_state">initial_state()</a>}</tt></li> +<li><tt><a name="type-initial_state">initial_state()</a> = term()</tt></li> </ul></p> </div><p>Same as send_req/3. - If a list is specified for the body it has to be a flat list.</p> + If a list is specified for the body it has to be a flat list. The body can also be a fun/0 or a fun/1. <br> + If fun/0, the connection handling process will repeatdely call the fun until it returns an error or eof. <pre>Fun() = {ok, Data} | eof</pre><br> + If fun/1, the connection handling process will repeatedly call the fun with the supplied state until it returns an error or eof. <pre>Fun(State) = {ok, Data} | {ok, Data, NewState} | eof</pre></p> <h3 class="function"><a name="send_req-5">send_req/5</a></h3> <div class="spec"> @@ -354,6 +357,6 @@ <hr> <div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> -<p><i>Generated by EDoc, Mar 27 2008, 01:03:49.</i></p> +<p><i>Generated by EDoc, Mar 27 2008, 01:20:55.</i></p> </body> </html> |
From: Chandru <cha...@us...> - 2008-03-27 01:36:26
|
Update of /cvsroot/jungerl/jungerl/lib/ibrowse/src In directory sc8-pr-cvs17.sourceforge.net:/tmp/cvs-serv28461/src Added Files: ibrowse_lb.erl Log Message: Lots of new features --- NEW FILE: ibrowse_lb.erl --- %%%------------------------------------------------------------------- %%% File : ibrowse_lb.erl %%% Author : chandru <cha...@t-...> %%% Description : %%% %%% Created : 6 Mar 2008 by chandru <cha...@t-...> %%%------------------------------------------------------------------- -module(ibrowse_lb). -vsn('$Id: ibrowse_lb.erl,v 1.1 2008/03/27 01:36:21 chandrusf Exp $ '). -author(chandru). -behaviour(gen_server). %%-------------------------------------------------------------------- %% Include files %%-------------------------------------------------------------------- %%-------------------------------------------------------------------- %% External exports -export([ start_link/1, spawn_connection/5 ]). %% gen_server callbacks -export([ init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3 ]). -record(state, {parent_pid, ets_tid, host, port, max_sessions, max_pipeline_size, num_cur_sessions = 0}). -import(ibrowse_lib, [ parse_url/1, printable_date/0, get_value/3 ]). -include("ibrowse.hrl"). %%==================================================================== %% External functions %%==================================================================== %%-------------------------------------------------------------------- %% Function: start_link/0 %% Description: Starts the server %%-------------------------------------------------------------------- start_link(Args) -> gen_server:start_link(?MODULE, Args, []). %%==================================================================== %% Server functions %%==================================================================== %%-------------------------------------------------------------------- %% Function: init/1 %% Description: Initiates the server %% Returns: {ok, State} | %% {ok, State, Timeout} | %% ignore | %% {stop, Reason} %%-------------------------------------------------------------------- init([Host, Port]) -> process_flag(trap_exit, true), Max_sessions = ibrowse:get_config_value({max_sessions, Host, Port}, 10), Max_pipe_sz = ibrowse:get_config_value({max_pipeline_size, Host, Port}, 10), put(my_trace_flag, ibrowse_lib:get_trace_status(Host, Port)), put(ibrowse_trace_token, ["LB: ", Host, $:, integer_to_list(Port)]), Tid = ets:new(ibrowse_lb, [public, ordered_set]), {ok, #state{parent_pid = whereis(ibrowse), host = Host, port = Port, ets_tid = Tid, max_pipeline_size = Max_pipe_sz, max_sessions = Max_sessions}}. spawn_connection(Lb_pid, Url, Max_sessions, Max_pipeline_size, SSL_options) when is_pid(Lb_pid), is_record(Url, url), is_integer(Max_pipeline_size), is_integer(Max_sessions) -> gen_server:call(Lb_pid, {spawn_connection, Url, Max_sessions, Max_pipeline_size, SSL_options}). %%-------------------------------------------------------------------- %% Function: handle_call/3 %% Description: Handling call messages %% Returns: {reply, Reply, State} | %% {reply, Reply, State, Timeout} | %% {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, Reply, State} | (terminate/2 is called) %% {stop, Reason, State} (terminate/2 is called) %%-------------------------------------------------------------------- % handle_call({spawn_connection, _Url, Max_sess, Max_pipe, _}, _From, % #state{max_sessions = Max_sess, % ets_tid = Tid, % max_pipeline_size = Max_pipe_sz, % num_cur_sessions = Num} = State) % when Num >= Max -> % Reply = find_best_connection(Tid), % {reply, sorry_dude_reuse, State}; %% Update max_sessions in #state with supplied value handle_call({spawn_connection, _Url, Max_sess, Max_pipe, _}, _From, #state{ets_tid = Tid, num_cur_sessions = Num} = State) when Num >= Max_sess -> Reply = find_best_connection(Tid, Max_pipe), {reply, Reply, State#state{max_sessions = Max_sess}}; handle_call({spawn_connection, Url, _Max_sess, _Max_pipe, SSL_options}, _From, #state{num_cur_sessions = Cur, ets_tid = Tid} = State) -> {ok, Pid} = ibrowse_http_client:start_link({Tid, Url, SSL_options}), ets:insert(Tid, {{1, Pid}, []}), {reply, {ok, Pid}, State#state{num_cur_sessions = Cur + 1}}; handle_call(Request, _From, State) -> Reply = {unknown_request, Request}, {reply, Reply, State}. %%-------------------------------------------------------------------- %% Function: handle_cast/2 %% Description: Handling cast messages %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%-------------------------------------------------------------------- handle_cast(_Msg, State) -> {noreply, State}. %%-------------------------------------------------------------------- %% Function: handle_info/2 %% Description: Handling all non call/cast messages %% Returns: {noreply, State} | %% {noreply, State, Timeout} | %% {stop, Reason, State} (terminate/2 is called) %%-------------------------------------------------------------------- handle_info({'EXIT', Parent, _Reason}, #state{parent_pid = Parent} = State) -> {stop, normal, State}; handle_info({'EXIT', Pid, _Reason}, #state{num_cur_sessions = Cur, ets_tid = Tid} = State) -> ets:match_delete(Tid, {{'_', Pid}, '_'}), {noreply, State#state{num_cur_sessions = Cur - 1}}; handle_info({trace, Bool}, State) -> put(my_trace_flag, Bool), {noreply, State}; handle_info(_Info, State) -> {noreply, State}. %%-------------------------------------------------------------------- %% Function: terminate/2 %% Description: Shutdown the server %% Returns: any (ignored by gen_server) %%-------------------------------------------------------------------- terminate(_Reason, _State) -> ok. %%-------------------------------------------------------------------- %% Func: code_change/3 %% Purpose: Convert process state when code is changed %% Returns: {ok, NewState} %%-------------------------------------------------------------------- code_change(_OldVsn, State, _Extra) -> {ok, State}. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- find_best_connection(Tid, Max_pipe) -> case ets:first(Tid) of {Cur_sz, Pid} when Cur_sz < Max_pipe -> ets:delete(Tid, {Cur_sz, Pid}), ets:insert(Tid, {{Cur_sz + 1, Pid}, []}), {ok, Pid}; _ -> {error, retry_later} end. |
From: Chandru <cha...@us...> - 2008-03-27 01:35:58
|
Update of /cvsroot/jungerl/jungerl/lib/ibrowse/ebin In directory sc8-pr-cvs17.sourceforge.net:/tmp/cvs-serv28029/ebin Modified Files: ibrowse.app Log Message: Lots of new features Index: ibrowse.app =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ibrowse/ebin/ibrowse.app,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- ibrowse.app 21 Mar 2007 08:57:57 -0000 1.1 +++ ibrowse.app 27 Mar 2008 01:35:49 -0000 1.2 @@ -1,10 +1,11 @@ {application, ibrowse, [{description, "HTTP client application"}, - {vsn, "1.2.5"}, + {vsn, "1.4"}, {modules, [ ibrowse, ibrowse_http_client, ibrowse_app, ibrowse_sup, + ibrowse_lb, ibrowse_lib ]}, {registered, []}, {applications, [kernel,stdlib,sasl]}, |
From: Chandru <cha...@us...> - 2008-03-27 01:35:58
|
Update of /cvsroot/jungerl/jungerl/lib/ibrowse In directory sc8-pr-cvs17.sourceforge.net:/tmp/cvs-serv28029 Modified Files: README vsn.mk Log Message: Lots of new features Index: README =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ibrowse/README,v retrieving revision 1.14 retrieving revision 1.15 diff -u -d -r1.14 -r1.15 --- README 27 Feb 2008 23:39:22 -0000 1.14 +++ README 27 Mar 2008 01:35:49 -0000 1.15 @@ -7,7 +7,7 @@ - Understands HTTP/0.9, HTTP/1.0 and HTTP/1.1 - Understands chunked encoding - Can generate requests using Chunked Transfer-Encoding - - Named pools of connections to each webserver + - Pools of connections to each webserver - Pipelining support - Download to file - Asynchronous requests. Responses are streamed to a process @@ -22,6 +22,26 @@ CONTRIBUTIONS & CHANGE HISTORY ============================== +27-03-2008 - * Major rewrite of the load balancing feature. Additional module, + ibrowse_lb.erl, introduced to achieve this. + * Can now get a handle to a connection process which is not part of + the load balancing pool. Useful when an application is making + requests to a webserver which are time consuming (such as + uploading a large file). Such requests can be put on a separate + connection, and all other smaller/quicker requests can use the + load balancing pool. See ibrowse:spawn_worker_process/2 and + ibrowse:spawn_link_worker_process/2 + * Ram Krishnan sent a patch to enable a client to send a lot of + data in a request by providing a fun which is invoked by the + connection handling process. This fun can fetch the data from + any where. This is useful when trying to upload a large file + to a webserver. + * Use the TCP_NODELAY option on every socket by default + * Rudimentary support for load testing of ibrowse. Undocumented, + but see ibrowse_test:load_test/3. Use the source, Luke! + * New function ibrowse:show_dest_status/2 to view state of + connections/pipelines to a web server + 20-02-2008 - Ram Krishnan sent another patch for another hidden bug in the save_response_to_file feature. Index: vsn.mk =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ibrowse/vsn.mk,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- vsn.mk 27 Feb 2008 23:39:22 -0000 1.12 +++ vsn.mk 27 Mar 2008 01:35:49 -0000 1.13 @@ -1,2 +1,2 @@ -IBROWSE_VSN = 1.3.1 +IBROWSE_VSN = 1.4 |
From: Chandru <cha...@us...> - 2008-03-27 01:35:58
|
Update of /cvsroot/jungerl/jungerl/lib/ibrowse/doc In directory sc8-pr-cvs17.sourceforge.net:/tmp/cvs-serv28029/doc Modified Files: ibrowse.html Log Message: Lots of new features Index: ibrowse.html =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ibrowse/doc/ibrowse.html,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- ibrowse.html 7 Feb 2008 12:02:12 -0000 1.5 +++ ibrowse.html 27 Mar 2008 01:35:49 -0000 1.6 @@ -10,15 +10,15 @@ <h1>Module ibrowse</h1> <ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>The ibrowse application implements an HTTP 1.1 client. -<p>Copyright © 2005-2007 Chandrashekhar Mullaparthi</p> +<p>Copyright © 2005-2008 Chandrashekhar Mullaparthi</p> -<p><b>Version:</b> 1.2.7</p> +<p><b>Version:</b> 1.4</p> <p><b>Behaviours:</b> <a href="gen_server.html"><tt>gen_server</tt></a>.</p> <p><b>Authors:</b> Chandrashekhar Mullaparthi (<a href="mailto:chandrashekhar dot mullaparthi at gmail dot com"><tt>chandrashekhar dot mullaparthi at gmail dot com</tt></a>).</p> <h2><a name="description">Description</a></h2><p>The ibrowse application implements an HTTP 1.1 client. This module implements the API of the HTTP client. There is one named -process called 'ibrowse' which acts as a load balancer. There is +process called 'ibrowse' which assists in load balancing and maintaining configuration. There is one load balancing process per unique webserver. There is one process to handle one TCP connection to a webserver (implemented in the module ibrowse_http_client). Multiple connections to a webserver are setup based on the settings for each webserver. The @@ -47,10 +47,6 @@ {save_response_to_file, true}], 1000). <br><br> - ibrowse:set_dest("www.hotmail.com", 80, [{max_sessions, 10}, - {max_pipeline_size, 1}]). - <br><br> - ibrowse:send_req("http://www.erlang.org", [], head). <br><br> @@ -69,21 +65,41 @@ driver isn't actually used.</p> <h2><a name="index">Function Index</a></h2> <table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr> -<tr><td valign="top"><a href="#finished_async_request-0">finished_async_request/0</a></td><td>Internal export.</td></tr> +<tr><td valign="top"><a href="#get_config_value-1">get_config_value/1</a></td><td>Internal export.</td></tr> +<tr><td valign="top"><a href="#get_config_value-2">get_config_value/2</a></td><td>Internal export.</td></tr> <tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr> <tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr> <tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr> <tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr> -<tr><td valign="top"><a href="#reply-2">reply/2</a></td><td>Internal export.</td></tr> +<tr><td valign="top"><a href="#rescan_config-0">rescan_config/0</a></td><td>Clear current configuration for ibrowse and load from the file + ibrowse.conf in the IBROWSE_EBIN/../priv directory.</td></tr> +<tr><td valign="top"><a href="#rescan_config-1">rescan_config/1</a></td><td></td></tr> <tr><td valign="top"><a href="#send_req-3">send_req/3</a></td><td>This is the basic function to send a HTTP request.</td></tr> <tr><td valign="top"><a href="#send_req-4">send_req/4</a></td><td>Same as send_req/3.</td></tr> <tr><td valign="top"><a href="#send_req-5">send_req/5</a></td><td>Same as send_req/4.</td></tr> <tr><td valign="top"><a href="#send_req-6">send_req/6</a></td><td>Same as send_req/5.</td></tr> -<tr><td valign="top"><a href="#set_dest-3">set_dest/3</a></td><td>Sets options for a destination.</td></tr> -<tr><td valign="top"><a href="#shutting_down-0">shutting_down/0</a></td><td>Internal export.</td></tr> -<tr><td valign="top"><a href="#start-0">start/0</a></td><td></td></tr> -<tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td></td></tr> -<tr><td valign="top"><a href="#stop-0">stop/0</a></td><td></td></tr> +<tr><td valign="top"><a href="#send_req_direct-4">send_req_direct/4</a></td><td>Same as send_req/3 except that the first argument is the PID + returned by spawn_worker_process/2 or spawn_link_worker_process/2.</td></tr> +<tr><td valign="top"><a href="#send_req_direct-5">send_req_direct/5</a></td><td>Same as send_req/4 except that the first argument is the PID + returned by spawn_worker_process/2 or spawn_link_worker_process/2.</td></tr> +<tr><td valign="top"><a href="#send_req_direct-6">send_req_direct/6</a></td><td>Same as send_req/5 except that the first argument is the PID + returned by spawn_worker_process/2 or spawn_link_worker_process/2.</td></tr> +<tr><td valign="top"><a href="#send_req_direct-7">send_req_direct/7</a></td><td>Same as send_req/6 except that the first argument is the PID + returned by spawn_worker_process/2 or spawn_link_worker_process/2.</td></tr> +<tr><td valign="top"><a href="#set_dest-3">set_dest/3</a></td><td>Deprecated.</td></tr> +<tr><td valign="top"><a href="#set_max_pipeline_size-3">set_max_pipeline_size/3</a></td><td>Set the maximum pipeline size for each connection to a specific Host:Port.</td></tr> +<tr><td valign="top"><a href="#set_max_sessions-3">set_max_sessions/3</a></td><td>Set the maximum number of connections allowed to a specific Host:Port.</td></tr> +<tr><td valign="top"><a href="#show_dest_status-2">show_dest_status/2</a></td><td>Shows some internal information about load balancing to a + specified Host:Port.</td></tr> +<tr><td valign="top"><a href="#spawn_link_worker_process-2">spawn_link_worker_process/2</a></td><td>Same as spawn_worker_process/2 except the the calling process + is linked to the worker process which is spawned.</td></tr> +<tr><td valign="top"><a href="#spawn_worker_process-2">spawn_worker_process/2</a></td><td>Creates a HTTP client process to the specified Host:Port which + is not part of the load balancing pool.</td></tr> +<tr><td valign="top"><a href="#start-0">start/0</a></td><td>Starts the ibrowse process without linking.</td></tr> +<tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td>Starts the ibrowse process linked to the calling process.</td></tr> +<tr><td valign="top"><a href="#stop-0">stop/0</a></td><td>Stop the ibrowse process.</td></tr> +<tr><td valign="top"><a href="#stop_worker_process-1">stop_worker_process/1</a></td><td>Terminate a worker process spawned using + spawn_worker_process/2 or spawn_link_worker_process/2.</td></tr> <tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr> <tr><td valign="top"><a href="#trace_off-0">trace_off/0</a></td><td>Turn tracing off for the ibrowse process.</td></tr> <tr><td valign="top"><a href="#trace_off-2">trace_off/2</a></td><td>Turn tracing OFF for all connections to the specified HTTP @@ -100,12 +116,15 @@ <p><tt>code_change() -> term()</tt></p> </div> -<h3 class="function"><a name="finished_async_request-0">finished_async_request/0</a></h3> +<h3 class="function"><a name="get_config_value-1">get_config_value/1</a></h3> <div class="spec"> -<p><tt>finished_async_request() -> term()</tt></p> -</div><p>Internal export. Called by a HTTP connection process to - indicate to the load balancing process (ibrowse) that an - asynchronous request has finished processing.</p> +<p><tt>get_config_value() -> term()</tt></p> +</div><p>Internal export</p> + +<h3 class="function"><a name="get_config_value-2">get_config_value/2</a></h3> +<div class="spec"> +<p><tt>get_config_value() -> term()</tt></p> +</div><p>Internal export</p> <h3 class="function"><a name="handle_call-3">handle_call/3</a></h3> <div class="spec"> @@ -127,12 +146,18 @@ <p><tt>init() -> term()</tt></p> </div> -<h3 class="function"><a name="reply-2">reply/2</a></h3> +<h3 class="function"><a name="rescan_config-0">rescan_config/0</a></h3> <div class="spec"> -<p><tt>reply() -> term()</tt></p> -</div><p>Internal export. Called by a HTTP connection process to - indicate to the load balancing process (ibrowse) that a synchronous - request has finished processing.</p> +<p><tt>rescan_config() -> term()</tt></p> +</div><p>Clear current configuration for ibrowse and load from the file + ibrowse.conf in the IBROWSE_EBIN/../priv directory. Current + configuration is cleared only if the ibrowse.conf file is readable + using file:consult/1</p> + +<h3 class="function"><a name="rescan_config-1">rescan_config/1</a></h3> +<div class="spec"> +<p><tt>rescan_config() -> term()</tt></p> +</div> <h3 class="function"><a name="send_req-3">send_req/3</a></h3> <div class="spec"> @@ -205,47 +230,97 @@ </div><p>Same as send_req/5. All timeout values are in milliseconds.</p> +<h3 class="function"><a name="send_req_direct-4">send_req_direct/4</a></h3> +<div class="spec"> +<p><tt>send_req_direct() -> term()</tt></p> +</div><p>Same as send_req/3 except that the first argument is the PID + returned by spawn_worker_process/2 or spawn_link_worker_process/2</p> + +<h3 class="function"><a name="send_req_direct-5">send_req_direct/5</a></h3> +<div class="spec"> +<p><tt>send_req_direct() -> term()</tt></p> +</div><p>Same as send_req/4 except that the first argument is the PID + returned by spawn_worker_process/2 or spawn_link_worker_process/2</p> + +<h3 class="function"><a name="send_req_direct-6">send_req_direct/6</a></h3> +<div class="spec"> +<p><tt>send_req_direct() -> term()</tt></p> +</div><p>Same as send_req/5 except that the first argument is the PID + returned by spawn_worker_process/2 or spawn_link_worker_process/2</p> + +<h3 class="function"><a name="send_req_direct-7">send_req_direct/7</a></h3> +<div class="spec"> +<p><tt>send_req_direct() -> term()</tt></p> +</div><p>Same as send_req/6 except that the first argument is the PID + returned by spawn_worker_process/2 or spawn_link_worker_process/2</p> + <h3 class="function"><a name="set_dest-3">set_dest/3</a></h3> <div class="spec"> -<p><tt>set_dest(Host::string(), Port::integer(), Opts::<a href="#type-opt_list">opt_list()</a>) -> ok</tt> -<ul class="definitions"><li><tt><a name="type-opt_list">opt_list()</a> = [opt]</tt></li> -<li><tt><a name="type-opt">opt()</a> = {max_sessions, integer()} | {max_pipeline_size, integer()} | {trace, <a href="#type-boolean">boolean()</a>}</tt></li> -</ul></p> -</div><p>Sets options for a destination. If the options have not been - set in the ibrowse.conf file, it can be set using this function - before sending the first request to the destination. If not, - defaults will be used. Entries in ibrowse.conf look like this. - <code><br> - {dest, Host, Port, MaxSess, MaxPipe, Options}.<br> - where <br> - Host = string(). "www.erlang.org" | "193.180.168.23"<br> - Port = integer()<br> - MaxSess = integer()<br> - MaxPipe = integer()<br> - Options = optionList() -- see options in send_req/5<br> - </code></p> +<p><tt>set_dest() -> term()</tt></p> +</div><p>Deprecated. Use set_max_sessions/3 and set_max_pipeline_size/3 + for achieving the same effect.</p> -<h3 class="function"><a name="shutting_down-0">shutting_down/0</a></h3> +<h3 class="function"><a name="set_max_pipeline_size-3">set_max_pipeline_size/3</a></h3> <div class="spec"> -<p><tt>shutting_down() -> term()</tt></p> -</div><p>Internal export. Called by a HTTP connection process to - indicate to ibrowse that it is shutting down and further requests - should not be sent it's way.</p> +<p><tt>set_max_pipeline_size(Host::string(), Port::integer(), Max::integer()) -> ok</tt></p> +</div><p>Set the maximum pipeline size for each connection to a specific Host:Port.</p> + +<h3 class="function"><a name="set_max_sessions-3">set_max_sessions/3</a></h3> +<div class="spec"> +<p><tt>set_max_sessions(Host::string(), Port::integer(), Max::integer()) -> ok</tt></p> +</div><p>Set the maximum number of connections allowed to a specific Host:Port.</p> + +<h3 class="function"><a name="show_dest_status-2">show_dest_status/2</a></h3> +<div class="spec"> +<p><tt>show_dest_status() -> term()</tt></p> +</div><p>Shows some internal information about load balancing to a + specified Host:Port. Info about workers spawned using + spawn_worker_process/2 or spawn_link_worker_process/2 is not + included.</p> + +<h3 class="function"><a name="spawn_link_worker_process-2">spawn_link_worker_process/2</a></h3> +<div class="spec"> +<p><tt>spawn_link_worker_process() -> term()</tt></p> +</div><p>Same as spawn_worker_process/2 except the the calling process + is linked to the worker process which is spawned.</p> + +<h3 class="function"><a name="spawn_worker_process-2">spawn_worker_process/2</a></h3> +<div class="spec"> +<p><tt>spawn_worker_process(Host::string(), Port::integer()) -> {ok, pid()}</tt></p> +</div><p>Creates a HTTP client process to the specified Host:Port which + is not part of the load balancing pool. This is useful in cases + where some requests to a webserver might take a long time whereas + some might take a very short time. To avoid getting these quick + requests stuck in the pipeline behind time consuming requests, use + this function to get a handle to a connection process. <br> + <b>Note:</b> Calling this function only creates a worker process. No connection + is setup. The connection attempt is made only when the first + request is sent via any of the send_req_direct/4,5,6,7 functions.<br> + <b>Note:</b> It is the responsibility of the calling process to control + pipeline size on such connections. + </p> <h3 class="function"><a name="start-0">start/0</a></h3> <div class="spec"> <p><tt>start() -> term()</tt></p> -</div> +</div><p>Starts the ibrowse process without linking. Useful when testing using the shell</p> <h3 class="function"><a name="start_link-0">start_link/0</a></h3> <div class="spec"> -<p><tt>start_link() -> term()</tt></p> -</div> +<p><tt>start_link() -> {ok, pid()}</tt></p> +</div><p>Starts the ibrowse process linked to the calling process. Usually invoked by the supervisor ibrowse_sup</p> <h3 class="function"><a name="stop-0">stop/0</a></h3> <div class="spec"> <p><tt>stop() -> term()</tt></p> -</div> +</div><p>Stop the ibrowse process. Useful when testing using the shell.</p> + +<h3 class="function"><a name="stop_worker_process-1">stop_worker_process/1</a></h3> +<div class="spec"> +<p><tt>stop_worker_process(Conn_pid::pid()) -> ok</tt></p> +</div><p>Terminate a worker process spawned using + spawn_worker_process/2 or spawn_link_worker_process/2. Requests in + progress will get the error response <pre>{error, closing_on_request}</pre></p> <h3 class="function"><a name="terminate-2">terminate/2</a></h3> <div class="spec"> @@ -279,6 +354,6 @@ <hr> <div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> -<p><i>Generated by EDoc, Feb 7 2008, 11:49:30.</i></p> +<p><i>Generated by EDoc, Mar 27 2008, 01:03:49.</i></p> </body> </html> |
From: Chandru <cha...@us...> - 2008-02-27 23:39:32
|
Update of /cvsroot/jungerl/jungerl/lib/ibrowse In directory sc8-pr-cvs6.sourceforge.net:/tmp/cvs-serv11290 Modified Files: README vsn.mk Log Message: Another fix for the save_response_to_file feature Index: README =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ibrowse/README,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- README 7 Feb 2008 12:02:10 -0000 1.13 +++ README 27 Feb 2008 23:39:22 -0000 1.14 @@ -22,6 +22,9 @@ CONTRIBUTIONS & CHANGE HISTORY ============================== +20-02-2008 - Ram Krishnan sent another patch for another hidden bug in the + save_response_to_file feature. + 07-02-2008 - Ram Krishnan (kriyative _at_ gmail dot com) sent a simple patch to enable specifying the filename in the save_response_to_file option. When testing the patch, I realised that my original implementation Index: vsn.mk =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ibrowse/vsn.mk,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- vsn.mk 7 Feb 2008 12:02:11 -0000 1.11 +++ vsn.mk 27 Feb 2008 23:39:22 -0000 1.12 @@ -1,2 +1,2 @@ -IBROWSE_VSN = 1.3.0 +IBROWSE_VSN = 1.3.1 |
From: Chandru <cha...@us...> - 2008-02-27 23:39:32
|
Update of /cvsroot/jungerl/jungerl/lib/ibrowse/src In directory sc8-pr-cvs6.sourceforge.net:/tmp/cvs-serv11290/src Modified Files: ibrowse_http_client.erl Log Message: Another fix for the save_response_to_file feature Index: ibrowse_http_client.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ibrowse/src/ibrowse_http_client.erl,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- ibrowse_http_client.erl 7 Feb 2008 12:02:13 -0000 1.15 +++ ibrowse_http_client.erl 27 Feb 2008 23:39:23 -0000 1.16 @@ -874,7 +874,6 @@ %% This clause to extract the body when Content-Length is specified parse_11_response(DataRecvd, #state{content_length=CL, rep_buf_size=RepBufSz, - cur_req = CurReq, reqs=Reqs}=State) -> NeedBytes = CL - RepBufSz, DataLen = length(DataRecvd), @@ -883,7 +882,7 @@ {RemBody, Rem} = split_list_at(DataRecvd, NeedBytes), {_, Reqs_1} = queue:out(Reqs), State_1 = accumulate_response(RemBody, State), - State_2 = handle_response(CurReq, State_1#state{reqs=Reqs_1}), + State_2 = handle_response(State_1#state.cur_req, State_1#state{reqs=Reqs_1}), State_3 = reset_state(State_2), parse_response(Rem, State_3); false -> |
From: Chandru <cha...@us...> - 2008-02-07 12:02:23
|
Update of /cvsroot/jungerl/jungerl/lib/ibrowse/doc In directory sc8-pr-cvs6.sourceforge.net:/tmp/cvs-serv1196/doc Modified Files: ibrowse.html Log Message: A mofidied version of a patch sent in by Ram Krishnan to enhance the save_response_to_file option Index: ibrowse.html =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ibrowse/doc/ibrowse.html,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- ibrowse.html 28 Jun 2007 22:29:01 -0000 1.4 +++ ibrowse.html 7 Feb 2008 12:02:12 -0000 1.5 @@ -2,14 +2,16 @@ <html> <head> <title>Module ibrowse</title> -<link rel="stylesheet" type="text/css" href="stylesheet.css"> +<link rel="stylesheet" type="text/css" href="stylesheet.css" title="EDoc"> </head> <body bgcolor="white"> +<div class="navbar"><a name="#navbar_top"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<hr> <h1>Module ibrowse</h1> -The ibrowse application implements an HTTP 1.1 client. +<ul class="index"><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul>The ibrowse application implements an HTTP 1.1 client. <p>Copyright © 2005-2007 Chandrashekhar Mullaparthi</p> -<ul><li><a href="#description">Description</a></li><li><a href="#index">Function Index</a></li><li><a href="#functions">Function Details</a></li></ul> + <p><b>Version:</b> 1.2.7</p> <p><b>Behaviours:</b> <a href="gen_server.html"><tt>gen_server</tt></a>.</p> <p><b>Authors:</b> Chandrashekhar Mullaparthi (<a href="mailto:chandrashekhar dot mullaparthi at gmail dot com"><tt>chandrashekhar dot mullaparthi at gmail dot com</tt></a>).</p> @@ -66,12 +68,12 @@ speed achieved using only erlang has been good enough, so the driver isn't actually used.</p> <h2><a name="index">Function Index</a></h2> -<table width="100%" border="1"><tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td/></tr> +<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#code_change-3">code_change/3</a></td><td></td></tr> <tr><td valign="top"><a href="#finished_async_request-0">finished_async_request/0</a></td><td>Internal export.</td></tr> -<tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td/></tr> -<tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td/></tr> -<tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td/></tr> -<tr><td valign="top"><a href="#init-1">init/1</a></td><td/></tr> +<tr><td valign="top"><a href="#handle_call-3">handle_call/3</a></td><td></td></tr> +<tr><td valign="top"><a href="#handle_cast-2">handle_cast/2</a></td><td></td></tr> +<tr><td valign="top"><a href="#handle_info-2">handle_info/2</a></td><td></td></tr> +<tr><td valign="top"><a href="#init-1">init/1</a></td><td></td></tr> <tr><td valign="top"><a href="#reply-2">reply/2</a></td><td>Internal export.</td></tr> <tr><td valign="top"><a href="#send_req-3">send_req/3</a></td><td>This is the basic function to send a HTTP request.</td></tr> <tr><td valign="top"><a href="#send_req-4">send_req/4</a></td><td>Same as send_req/3.</td></tr> @@ -79,10 +81,10 @@ <tr><td valign="top"><a href="#send_req-6">send_req/6</a></td><td>Same as send_req/5.</td></tr> <tr><td valign="top"><a href="#set_dest-3">set_dest/3</a></td><td>Sets options for a destination.</td></tr> <tr><td valign="top"><a href="#shutting_down-0">shutting_down/0</a></td><td>Internal export.</td></tr> -<tr><td valign="top"><a href="#start-0">start/0</a></td><td/></tr> -<tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td/></tr> -<tr><td valign="top"><a href="#stop-0">stop/0</a></td><td/></tr> -<tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td/></tr> +<tr><td valign="top"><a href="#start-0">start/0</a></td><td></td></tr> +<tr><td valign="top"><a href="#start_link-0">start_link/0</a></td><td></td></tr> +<tr><td valign="top"><a href="#stop-0">stop/0</a></td><td></td></tr> +<tr><td valign="top"><a href="#terminate-2">terminate/2</a></td><td></td></tr> <tr><td valign="top"><a href="#trace_off-0">trace_off/0</a></td><td>Turn tracing off for the ibrowse process.</td></tr> <tr><td valign="top"><a href="#trace_off-2">trace_off/2</a></td><td>Turn tracing OFF for all connections to the specified HTTP server.</td></tr> @@ -93,54 +95,86 @@ <h2><a name="functions">Function Details</a></h2> -<h3><a name="code_change-3">code_change/3</a></h3> -<tt>code_change(OldVsn, State, Extra) -> term() -</tt> +<h3 class="function"><a name="code_change-3">code_change/3</a></h3> +<div class="spec"> +<p><tt>code_change() -> term()</tt></p> +</div> -<h3><a name="finished_async_request-0">finished_async_request/0</a></h3> -<tt>finished_async_request() -> term() -</tt><p>Internal export. Called by a HTTP connection process to +<h3 class="function"><a name="finished_async_request-0">finished_async_request/0</a></h3> +<div class="spec"> +<p><tt>finished_async_request() -> term()</tt></p> +</div><p>Internal export. Called by a HTTP connection process to indicate to the load balancing process (ibrowse) that an asynchronous request has finished processing.</p> -<h3><a name="handle_call-3">handle_call/3</a></h3> -<tt>handle_call(Req, From, State) -> term() -</tt> +<h3 class="function"><a name="handle_call-3">handle_call/3</a></h3> +<div class="spec"> +<p><tt>handle_call() -> term()</tt></p> +</div> -<h3><a name="handle_cast-2">handle_cast/2</a></h3> -<tt>handle_cast(Msg, State) -> term() -</tt> +<h3 class="function"><a name="handle_cast-2">handle_cast/2</a></h3> +<div class="spec"> +<p><tt>handle_cast() -> term()</tt></p> +</div> -<h3><a name="handle_info-2">handle_info/2</a></h3> -<tt>handle_info(Info, State) -> term() -</tt> +<h3 class="function"><a name="handle_info-2">handle_info/2</a></h3> +<div class="spec"> +<p><tt>handle_info() -> term()</tt></p> +</div> -<h3><a name="init-1">init/1</a></h3> -<tt>init(X1) -> term() -</tt> +<h3 class="function"><a name="init-1">init/1</a></h3> +<div class="spec"> +<p><tt>init() -> term()</tt></p> +</div> -<h3><a name="reply-2">reply/2</a></h3> -<tt>reply(OrigCaller, Reply) -> term() -</tt><p>Internal export. Called by a HTTP connection process to +<h3 class="function"><a name="reply-2">reply/2</a></h3> +<div class="spec"> +<p><tt>reply() -> term()</tt></p> +</div><p>Internal export. Called by a HTTP connection process to indicate to the load balancing process (ibrowse) that a synchronous request has finished processing.</p> -<h3><a name="send_req-3">send_req/3</a></h3> +<h3 class="function"><a name="send_req-3">send_req/3</a></h3> +<div class="spec"> <p><tt>send_req(Url::string(), Headers::<a href="#type-headerList">headerList()</a>, Method::<a href="#type-method">method()</a>) -> <a href="#type-response">response()</a></tt> -<ul><li><tt><a name="type-headerList">headerList()</a> = [{<a href="#type-header">header()</a>, <a href="#type-value">value()</a>}]</tt></li><li><tt><a name="type-header">header()</a> = atom() | string()</tt></li><li><tt><a name="type-value">value()</a> = term()</tt></li><li><tt><a name="type-method">method()</a> = get | post | head | options | put | delete | trace | mkcol | propfind | proppatch | lock | unlock | move | copy</tt></li><li><tt>Status = string()</tt></li><li><tt>ResponseHeaders = [<a href="#type-respHeader">respHeader()</a>]</tt></li><li><tt><a name="type-respHeader">respHeader()</a> = {<a href="#type-headerName">headerName()</a>, <a href="#type-headerValue">headerValue()</a>}</tt></li><li><tt><a name="type-headerName">headerName()</a> = string()</tt></li><li><tt><a name="type-headerValue">headerValue()</a> = string()</tt></li><li><tt><a name="type-response">response()</a> = {ok, Status, ResponseHeaders, ResponseBody} | {error, Reason}</tt></li><li><tt>ResponseBody = string()</tt></li><li><tt>Reason = term()</tt></li></ul></p> -<p>This is the basic function to send a HTTP request. +<ul class="definitions"><li><tt><a name="type-headerList">headerList()</a> = [{<a href="#type-header">header()</a>, <a href="#type-value">value()</a>}]</tt></li> +<li><tt><a name="type-header">header()</a> = atom() | string()</tt></li> +<li><tt><a name="type-value">value()</a> = term()</tt></li> +<li><tt><a name="type-method">method()</a> = get | post | head | options | put | delete | trace | mkcol | propfind | proppatch | lock | unlock | move | copy</tt></li> +<li><tt>Status = string()</tt></li> +<li><tt>ResponseHeaders = [<a href="#type-respHeader">respHeader()</a>]</tt></li> +<li><tt><a name="type-respHeader">respHeader()</a> = {<a href="#type-headerName">headerName()</a>, <a href="#type-headerValue">headerValue()</a>}</tt></li> +<li><tt><a name="type-headerName">headerName()</a> = string()</tt></li> +<li><tt><a name="type-headerValue">headerValue()</a> = string()</tt></li> +<li><tt><a name="type-response">response()</a> = {ok, Status, ResponseHeaders, ResponseBody} | {error, Reason}</tt></li> +<li><tt>ResponseBody = string() | {file, Filename}</tt></li> +<li><tt>Reason = term()</tt></li> +</ul></p> +</div><p>This is the basic function to send a HTTP request. The Status return value indicates the HTTP status code returned by the webserver</p> -<h3><a name="send_req-4">send_req/4</a></h3> +<h3 class="function"><a name="send_req-4">send_req/4</a></h3> +<div class="spec"> <p><tt>send_req(Url, Headers, Method::<a href="#type-method">method()</a>, Body::<a href="#type-body">body()</a>) -> <a href="#type-response">response()</a></tt> -<ul><li><tt><a name="type-body">body()</a> = [] | string() | binary()</tt></li></ul></p> -<p>Same as send_req/3. +<ul class="definitions"><li><tt><a name="type-body">body()</a> = [] | string() | binary()</tt></li> +</ul></p> +</div><p>Same as send_req/3. If a list is specified for the body it has to be a flat list.</p> -<h3><a name="send_req-5">send_req/5</a></h3> +<h3 class="function"><a name="send_req-5">send_req/5</a></h3> +<div class="spec"> <p><tt>send_req(Url::string(), Headers::<a href="#type-headerList">headerList()</a>, Method::<a href="#type-method">method()</a>, Body::<a href="#type-body">body()</a>, Options::<a href="#type-optionList">optionList()</a>) -> <a href="#type-response">response()</a></tt> -<ul><li><tt><a name="type-optionList">optionList()</a> = [<a href="#type-option">option()</a>]</tt></li><li><tt><a name="type-option">option()</a> = {max_sessions, integer()} | {max_pipeline_size, integer()} | {trace, <a href="#type-boolean">boolean()</a>} | {is_ssl, <a href="#type-boolean">boolean()</a>} | {ssl_options, [SSLOpt]} | {pool_name, atom()} | {proxy_host, string()} | {proxy_port, integer()} | {proxy_user, string()} | {proxy_password, string()} | {use_absolute_uri, <a href="#type-boolean">boolean()</a>} | {basic_auth, {<a href="#type-username">username()</a>, <a href="#type-password">password()</a>}} | {cookie, string()} | {content_length, integer()} | {content_type, string()} | {save_response_to_file, <a href="#type-boolean">boolean()</a>} | {stream_to, <a href="#type-process">process()</a>} | {http_vsn, {MajorVsn, MinorVsn}} | {host_header, string()} | {transfer_encoding, {chunked, ChunkSize}}</tt></li><li><tt><a name="type-process">process()</a> = pid() | atom()</tt></li><li><tt><a name="type-username">username()</a> = string()</tt></li><li><tt><a name="type-password">password()</a> = string()</tt></li><li><tt>SSLOpt = term()</tt></li><li><tt>ChunkSize = integer()</tt></li></ul></p> -<p>Same as send_req/4. +<ul class="definitions"><li><tt><a name="type-optionList">optionList()</a> = [<a href="#type-option">option()</a>]</tt></li> +<li><tt><a name="type-option">option()</a> = {max_sessions, integer()} | {max_pipeline_size, integer()} | {trace, <a href="#type-boolean">boolean()</a>} | {is_ssl, <a href="#type-boolean">boolean()</a>} | {ssl_options, [SSLOpt]} | {pool_name, atom()} | {proxy_host, string()} | {proxy_port, integer()} | {proxy_user, string()} | {proxy_password, string()} | {use_absolute_uri, <a href="#type-boolean">boolean()</a>} | {basic_auth, {<a href="#type-username">username()</a>, <a href="#type-password">password()</a>}} | {cookie, string()} | {content_length, integer()} | {content_type, string()} | {save_response_to_file, <a href="#type-srtf">srtf()</a>} | {stream_to, <a href="#type-process">process()</a>} | {http_vsn, {MajorVsn, MinorVsn}} | {host_header, string()} | {transfer_encoding, {chunked, ChunkSize}}</tt></li> +<li><tt><a name="type-process">process()</a> = pid() | atom()</tt></li> +<li><tt><a name="type-username">username()</a> = string()</tt></li> +<li><tt><a name="type-password">password()</a> = string()</tt></li> +<li><tt>SSLOpt = term()</tt></li> +<li><tt>ChunkSize = integer()</tt></li> +<li><tt><a name="type-srtf">srtf()</a> = <a href="#type-boolean">boolean()</a> | <a href="#type-filename">filename()</a></tt></li> +<li><tt><a name="type-filename">filename()</a> = string()</tt></li> +</ul></p> +</div><p>Same as send_req/4. For a description of SSL Options, look in the ssl manpage. If the HTTP Version to use is not specified, the default is 1.1. <br> @@ -150,18 +184,34 @@ ibrowse must have the stunnel host/port details, but that won't make sense to the destination webserver. This option can then be used to specify what should go in the <code>Host</code> header in - the request.</p></p> + the request.</p> + <ul> + <li>When both the options <code>save_response_to_file</code> and <code>stream_to</code> + are specified, the former takes precedence.</li> + + <li>For the <code>save_response_to_file</code> option, the response body is saved to + file only if the status code is in the 200-299 range. If not, the response body is returned + as a string.</li> + <li>Whenever an error occurs in the processing of a request, ibrowse will return as much + information as it has, such as HTTP Status Code and HTTP Headers. When this happens, the response + is of the form <code>{error, {Reason, {stat_code, StatusCode}, HTTP_headers}}</code></li> + </ul></p> -<h3><a name="send_req-6">send_req/6</a></h3> +<h3 class="function"><a name="send_req-6">send_req/6</a></h3> +<div class="spec"> <p><tt>send_req(Url, Headers::<a href="#type-headerList">headerList()</a>, Method::<a href="#type-method">method()</a>, Body::<a href="#type-body">body()</a>, Options::<a href="#type-optionList">optionList()</a>, Timeout) -> <a href="#type-response">response()</a></tt> -<ul><li><tt>Timeout = integer() | infinity</tt></li></ul></p> -<p>Same as send_req/5. +<ul class="definitions"><li><tt>Timeout = integer() | infinity</tt></li> +</ul></p> +</div><p>Same as send_req/5. All timeout values are in milliseconds.</p> -<h3><a name="set_dest-3">set_dest/3</a></h3> +<h3 class="function"><a name="set_dest-3">set_dest/3</a></h3> +<div class="spec"> <p><tt>set_dest(Host::string(), Port::integer(), Opts::<a href="#type-opt_list">opt_list()</a>) -> ok</tt> -<ul><li><tt><a name="type-opt_list">opt_list()</a> = [opt]</tt></li><li><tt><a name="type-opt">opt()</a> = {max_sessions, integer()} | {max_pipeline_size, integer()} | {trace, <a href="#type-boolean">boolean()</a>}</tt></li></ul></p> -<p>Sets options for a destination. If the options have not been +<ul class="definitions"><li><tt><a name="type-opt_list">opt_list()</a> = [opt]</tt></li> +<li><tt><a name="type-opt">opt()</a> = {max_sessions, integer()} | {max_pipeline_size, integer()} | {trace, <a href="#type-boolean">boolean()</a>}</tt></li> +</ul></p> +</div><p>Sets options for a destination. If the options have not been set in the ibrowse.conf file, it can be set using this function before sending the first request to the destination. If not, defaults will be used. Entries in ibrowse.conf look like this. @@ -175,45 +225,60 @@ Options = optionList() -- see options in send_req/5<br> </code></p> -<h3><a name="shutting_down-0">shutting_down/0</a></h3> -<tt>shutting_down() -> term() -</tt><p>Internal export. Called by a HTTP connection process to +<h3 class="function"><a name="shutting_down-0">shutting_down/0</a></h3> +<div class="spec"> +<p><tt>shutting_down() -> term()</tt></p> +</div><p>Internal export. Called by a HTTP connection process to indicate to ibrowse that it is shutting down and further requests should not be sent it's way.</p> -<h3><a name="start-0">start/0</a></h3> -<tt>start() -> term() -</tt> +<h3 class="function"><a name="start-0">start/0</a></h3> +<div class="spec"> +<p><tt>start() -> term()</tt></p> +</div> -<h3><a name="start_link-0">start_link/0</a></h3> -<tt>start_link() -> term() -</tt> +<h3 class="function"><a name="start_link-0">start_link/0</a></h3> +<div class="spec"> +<p><tt>start_link() -> term()</tt></p> +</div> -<h3><a name="stop-0">stop/0</a></h3> -<tt>stop() -> term() -</tt> +<h3 class="function"><a name="stop-0">stop/0</a></h3> +<div class="spec"> +<p><tt>stop() -> term()</tt></p> +</div> -<h3><a name="terminate-2">terminate/2</a></h3> -<tt>terminate(Reason, State) -> term() -</tt> +<h3 class="function"><a name="terminate-2">terminate/2</a></h3> +<div class="spec"> +<p><tt>terminate() -> term()</tt></p> +</div> -<h3><a name="trace_off-0">trace_off/0</a></h3> -<tt>trace_off() -> term() -</tt><p>Turn tracing off for the ibrowse process</p> +<h3 class="function"><a name="trace_off-0">trace_off/0</a></h3> +<div class="spec"> +<p><tt>trace_off() -> term()</tt></p> +</div><p>Turn tracing off for the ibrowse process</p> -<h3><a name="trace_off-2">trace_off/2</a></h3> +<h3 class="function"><a name="trace_off-2">trace_off/2</a></h3> +<div class="spec"> <p><tt>trace_off(Host, Port) -> term()</tt></p> -<p>Turn tracing OFF for all connections to the specified HTTP +</div><p>Turn tracing OFF for all connections to the specified HTTP server.</p> -<h3><a name="trace_on-0">trace_on/0</a></h3> -<tt>trace_on() -> term() -</tt><p>Turn tracing on for the ibrowse process</p> +<h3 class="function"><a name="trace_on-0">trace_on/0</a></h3> +<div class="spec"> +<p><tt>trace_on() -> term()</tt></p> +</div><p>Turn tracing on for the ibrowse process</p> -<h3><a name="trace_on-2">trace_on/2</a></h3> +<h3 class="function"><a name="trace_on-2">trace_on/2</a></h3> +<div class="spec"> <p><tt>trace_on(Host, Port) -> term()</tt> -<ul><li><tt>Host = string()</tt></li><li><tt>Port = integer()</tt></li></ul></p> -<p>Turn tracing on for all connections to the specified HTTP +<ul class="definitions"><li><tt>Host = string()</tt></li> +<li><tt>Port = integer()</tt></li> +</ul></p> +</div><p>Turn tracing on for all connections to the specified HTTP server. Host is whatever is specified as the domain name in the URL</p> +<hr> + +<div class="navbar"><a name="#navbar_bottom"></a><table width="100%" border="0" cellspacing="0" cellpadding="2" summary="navigation bar"><tr><td><a href="overview-summary.html" target="overviewFrame">Overview</a></td><td><a href="http://www.erlang.org/"><img src="erlang.png" align="right" border="0" alt="erlang logo"></a></td></tr></table></div> +<p><i>Generated by EDoc, Feb 7 2008, 11:49:30.</i></p> </body> </html> |
From: Chandru <cha...@us...> - 2008-02-07 12:02:23
|
Update of /cvsroot/jungerl/jungerl/lib/ibrowse/src In directory sc8-pr-cvs6.sourceforge.net:/tmp/cvs-serv1196/src Modified Files: ibrowse.erl ibrowse_http_client.erl Log Message: A mofidied version of a patch sent in by Ram Krishnan to enhance the save_response_to_file option Index: ibrowse.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ibrowse/src/ibrowse.erl,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- ibrowse.erl 28 Jun 2007 22:29:01 -0000 1.4 +++ ibrowse.erl 7 Feb 2008 12:02:13 -0000 1.5 @@ -167,7 +167,7 @@ %% headerName() = string() %% headerValue() = string() %% response() = {ok, Status, ResponseHeaders, ResponseBody} | {error, Reason} -%% ResponseBody = string() +%% ResponseBody = string() | {file, Filename} %% Reason = term() send_req(Url, Headers, Method) -> send_req(Url, Headers, Method, [], []). @@ -191,6 +191,17 @@ %% make sense to the destination webserver. This option can then be %% used to specify what should go in the <code>Host</code> header in %% the request.</p> +%% <ul> +%% <li>When both the options <code>save_response_to_file</code> and <code>stream_to</code> +%% are specified, the former takes precedence.</li> +%% +%% <li>For the <code>save_response_to_file</code> option, the response body is saved to +%% file only if the status code is in the 200-299 range. If not, the response body is returned +%% as a string.</li> +%% <li>Whenever an error occurs in the processing of a request, ibrowse will return as much +%% information as it has, such as HTTP Status Code and HTTP Headers. When this happens, the response +%% is of the form <code>{error, {Reason, {stat_code, StatusCode}, HTTP_headers}}</code></li> +%% </ul> %% @spec send_req(Url::string(), Headers::headerList(), Method::method(), Body::body(), Options::optionList()) -> response() %% optionList() = [option()] %% option() = {max_sessions, integer()} | @@ -208,7 +219,7 @@ %% {cookie, string()} | %% {content_length, integer()} | %% {content_type, string()} | -%% {save_response_to_file, boolean()} | +%% {save_response_to_file, srtf()} | %% {stream_to, process()} | %% {http_vsn, {MajorVsn, MinorVsn}} | %% {host_header, string()} | @@ -219,6 +230,9 @@ %% password() = string() %% SSLOpt = term() %% ChunkSize = integer() +%% srtf() = boolean() | filename() +%% filename() = string() +%% send_req(Url, Headers, Method, Body, Options) -> send_req(Url, Headers, Method, Body, Options, 30000). Index: ibrowse_http_client.erl =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ibrowse/src/ibrowse_http_client.erl,v retrieving revision 1.14 retrieving revision 1.15 diff -u -d -r1.14 -r1.15 --- ibrowse_http_client.erl 19 Oct 2007 12:43:48 -0000 1.14 +++ ibrowse_http_client.erl 7 Feb 2008 12:02:13 -0000 1.15 @@ -35,11 +35,12 @@ reply_buffer=[], rep_buf_size=0, recvd_headers=[], is_closing, send_timer, content_length, deleted_crlf = false, transfer_encoding, chunk_size, - chunks=[], save_response_to_file = false, - tmp_file_name, tmp_file_fd}). + chunks=[]}). -record(request, {url, method, options, from, - stream_to, req_id}). + stream_to, req_id, + save_response_to_file = false, + tmp_file_name, tmp_file_fd}). %%==================================================================== %% External functions @@ -122,19 +123,19 @@ _PHost -> ProxyUser = get_value(proxy_user, Options, []), ProxyPassword = get_value(proxy_password, Options, []), - SaveResponseToFile = get_value(save_response_to_file, Options, false), Digest = http_auth_digest(ProxyUser, ProxyPassword), State#state{use_proxy = true, - save_response_to_file = SaveResponseToFile, proxy_auth_digest = Digest} end, StreamTo = get_value(stream_to, Options, undefined), ReqId = make_req_id(), + SaveResponseToFile = get_value(save_response_to_file, Options, false), NewReq = #request{url=Url, method=Method, stream_to=StreamTo, options=Options, req_id=ReqId, + save_response_to_file = SaveResponseToFile, from=From}, Reqs = queue:in(NewReq, State#state.reqs), State_2 = check_ssl_options(Options, State_1#state{reqs = Reqs}), @@ -185,12 +186,14 @@ #state{socket=Sock, status=Status, reqs=Reqs}=State) -> do_trace("Recvd request in connected state. Status -> ~p NumPending: ~p~n", [Status, length(queue:to_list(Reqs))]), StreamTo = get_value(stream_to, Options, undefined), + SaveResponseToFile = get_value(save_response_to_file, Options, false), ReqId = make_req_id(), NewReq = #request{url=Url, stream_to=StreamTo, method=Method, options=Options, req_id=ReqId, + save_response_to_file = SaveResponseToFile, from=From}, State_1 = State#state{reqs=queue:in(NewReq, State#state.reqs)}, case send_req_1(Url, Headers, Method, Body, Options, Sock, State_1) of @@ -309,18 +312,16 @@ end; handle_sock_data(Data, #state{status=get_body, content_length=CL, - recvd_headers=Headers, cur_req=CurReq, - chunk_size=CSz, reqs=Reqs, socket=Sock}=State) -> + http_status_code = StatCode, + recvd_headers=Headers, + chunk_size=CSz, socket=Sock}=State) -> case (CL == undefined) and (CSz == undefined) of true -> case accumulate_response(Data, State) of {error, Reason} -> ibrowse:shutting_down(), - {_, Reqs_1} = queue:out(Reqs), - #request{from=From, stream_to=StreamTo, req_id=ReqId} = CurReq, - do_reply(From, StreamTo, ReqId, - {error, {file_open_error, Reason, Headers}}), - do_error_reply(State#state{reqs=Reqs_1}, previous_request_failed), + fail_pipelined_requests(State, + {error, {Reason, {stat_code, StatCode}, Headers}}), {stop, normal, State}; State_1 -> do_setopts(Sock, [{active, true}], State#state.is_ssl), @@ -328,8 +329,10 @@ end; _ -> case parse_11_response(Data, State) of - {error, _Reason} -> + {error, Reason} -> ibrowse:shutting_down(), + fail_pipelined_requests(State, + {error, {Reason, {stat_code, StatCode}, Headers}}), {stop, normal, State}; stop -> ibrowse:shutting_down(), @@ -340,32 +343,41 @@ end end. -accumulate_response(Data, #state{save_response_to_file = true, - tmp_file_fd = undefined, - http_status_code=[$2 | _]}=State) -> - TmpFilename = make_tmp_filename(), +accumulate_response(Data, + #state{ + cur_req = #request{save_response_to_file = SaveResponseToFile, + tmp_file_fd = undefined} = CurReq, + http_status_code=[$2 | _]}=State) when SaveResponseToFile /= false -> + TmpFilename = case SaveResponseToFile of + true -> make_tmp_filename(); + F -> F + end, case file:open(TmpFilename, [write, delayed_write, raw]) of {ok, Fd} -> - accumulate_response(Data, State#state{tmp_file_fd=Fd, - tmp_file_name=TmpFilename}); + accumulate_response(Data, State#state{ + cur_req = CurReq#request{ + tmp_file_fd = Fd, + tmp_file_name = TmpFilename}}); {error, Reason} -> {error, {file_open_error, Reason}} end; -accumulate_response(Data, #state{save_response_to_file=true, +accumulate_response(Data, #state{cur_req = #request{save_response_to_file = SaveResponseToFile, + tmp_file_fd = Fd}, transfer_encoding=chunked, chunks = Chunks, - http_status_code=[$2 | _], - tmp_file_fd=Fd}=State) -> + http_status_code=[$2 | _] + } = State) when SaveResponseToFile /= false -> case file:write(Fd, [Chunks | Data]) of ok -> State#state{chunks = []}; {error, Reason} -> {error, {file_write_error, Reason}} end; -accumulate_response(Data, #state{save_response_to_file=true, +accumulate_response(Data, #state{cur_req = #request{save_response_to_file = SaveResponseToFile, + tmp_file_fd = Fd}, reply_buffer = RepBuf, - http_status_code=[$2 | _], - tmp_file_fd=Fd}=State) -> + http_status_code=[$2 | _] + } = State) when SaveResponseToFile /= false -> case file:write(Fd, [RepBuf | Data]) of ok -> State#state{reply_buffer = []}; @@ -374,8 +386,8 @@ end; accumulate_response([], State) -> State; -accumulate_response(Data, #state{reply_buffer=RepBuf, - cur_req=CurReq}=State) -> +accumulate_response(Data, #state{reply_buffer = RepBuf, + cur_req = CurReq}=State) -> #request{stream_to=StreamTo, req_id=ReqId} = CurReq, case StreamTo of undefined -> @@ -409,8 +421,9 @@ %% Connection-Close header and has closed the socket to indicate end %% of response. There maybe requests pipelined which need a response. handle_sock_closed(#state{reply_buffer=Buf, reqs=Reqs, http_status_code=SC, - is_closing=IsClosing, cur_req=CurReq, - tmp_file_name=TmpFilename, tmp_file_fd=Fd, + is_closing=IsClosing, + cur_req=#request{tmp_file_name=TmpFilename, + tmp_file_fd=Fd} = CurReq, status=get_body, recvd_headers=Headers}=State) -> #request{from=From, stream_to=StreamTo, req_id=ReqId} = CurReq, case IsClosing of @@ -635,7 +648,7 @@ parse_response(Data, #state{reply_buffer=Acc, reqs=Reqs, cur_req=CurReq}=State) -> #request{from=From, stream_to=StreamTo, req_id=ReqId, - options = CurReqOptions, method=Method} = CurReq, + method=Method} = CurReq, MaxHeaderSize = safe_get_env(ibrowse, max_headers_size, infinity), case scan_header(Data, Acc) of {yes, Headers, Data_1} -> @@ -652,10 +665,7 @@ false -> ok end, - SaveResponseToFile = get_value(save_response_to_file, CurReqOptions, false), State_1 = State#state{recvd_headers=Headers_1, status=get_body, - save_response_to_file = SaveResponseToFile, - tmp_file_fd = undefined, tmp_file_name = undefined, http_status_code=StatCode, is_closing=IsClosing}, put(conn_close, ConnClose), TransferEncoding = to_lower(get_value("transfer-encoding", LCHeaders, "false")), @@ -690,33 +700,47 @@ _ when TransferEncoding == "chunked" -> do_trace("Chunked encoding detected...~n",[]), send_async_headers(ReqId, StreamTo, StatCode, Headers_1), - parse_11_response(Data_1, State_1#state{transfer_encoding=chunked, - chunk_size=chunk_start, - reply_buffer=[], chunks=[]}); + case parse_11_response(Data_1, State_1#state{transfer_encoding=chunked, + chunk_size=chunk_start, + reply_buffer=[], chunks=[]}) of + {error, Reason} -> + fail_pipelined_requests(State_1, + {error, {Reason, + {stat_code, StatCode}, Headers_1}}), + {error, Reason}; + State_2 -> + State_2 + end; undefined when HttpVsn == "HTTP/1.0"; ConnClose == "close" -> send_async_headers(ReqId, StreamTo, StatCode, Headers_1), State_1#state{reply_buffer=[Data_1]}; undefined -> - {_, Reqs_1} = queue:out(Reqs), - do_reply(From, StreamTo, ReqId, - {error, {content_length_undefined, Headers}}), - do_error_reply(State_1#state{reqs=Reqs_1}, previous_request_failed), + fail_pipelined_requests(State_1, + {error, {content_length_undefined, + {stat_code, StatCode}, Headers}}), {error, content_length_undefined}; V -> case catch list_to_integer(V) of V_1 when integer(V_1), V_1 >= 0 -> send_async_headers(ReqId, StreamTo, StatCode, Headers_1), do_trace("Recvd Content-Length of ~p~n", [V_1]), - parse_11_response(Data_1, - State_1#state{rep_buf_size=0, - reply_buffer=[], - content_length=V_1}); + State_2 = State_1#state{rep_buf_size=0, + reply_buffer=[], + content_length=V_1}, + case parse_11_response(Data_1, State_2) of + {error, Reason} -> + fail_pipelined_requests(State_1, + {error, {Reason, + {stat_code, StatCode}, Headers_1}}), + {error, Reason}; + State_3 -> + State_3 + end; _ -> - {_, Reqs_1} = queue:out(Reqs), - do_reply(From, StreamTo, ReqId, - {error, {content_length_undefined, Headers}}), - do_error_reply(State_1#state{reqs=Reqs_1}, previous_request_failed), + fail_pipelined_requests(State_1, + {error, {content_length_undefined, + {stat_code, StatCode}, Headers}}), {error, content_length_undefined} end end; @@ -725,9 +749,7 @@ {no, Acc_1} when length(Acc_1) < MaxHeaderSize -> State#state{reply_buffer=Acc_1}; {no, _Acc_1} -> - do_reply(From, StreamTo, ReqId, {error, max_headers_size_exceeded}), - {_, Reqs_1} = queue:out(Reqs), - do_error_reply(State#state{reqs=Reqs_1}, previous_request_failed), + fail_pipelined_requests(State, {error, max_headers_size_exceeded}), {error, max_headers_size_exceeded} end. @@ -835,6 +857,7 @@ do_trace("RemData -> ~p~n", [RemData]), case accumulate_response(RemChunk, State) of {error, Reason} -> + do_trace("Error accumulating response --> ~p~n", [Reason]), {error, Reason}; #state{reply_buffer = NewRepBuf, chunks = NewChunks} = State_1 -> @@ -867,18 +890,34 @@ accumulate_response(DataRecvd, State#state{rep_buf_size=RepBufSz+DataLen}) end. -handle_response(#request{from=From, stream_to=StreamTo, req_id=ReqId}, - #state{save_response_to_file = true, - http_status_code=SCode, - tmp_file_name=TmpFilename, - tmp_file_fd=Fd, - send_timer=ReqTimer, - recvd_headers = RespHeaders}=State) -> +handle_response(#request{from=From, stream_to=StreamTo, req_id=ReqId, + save_response_to_file = SaveResponseToFile, + tmp_file_name = TmpFilename, + tmp_file_fd = Fd + }, + #state{http_status_code = SCode, + send_timer = ReqTimer, + reply_buffer = RepBuf, + transfer_encoding = TEnc, + chunks = Chunks, + recvd_headers = RespHeaders}=State) when SaveResponseToFile /= false -> + Body = case TEnc of + chunked -> + lists:flatten(lists:reverse(Chunks)); + _ -> + lists:flatten(lists:reverse(RepBuf)) + end, State_1 = set_cur_request(State), file:close(Fd), - do_reply(From, StreamTo, ReqId, {ok, SCode, RespHeaders, {file, TmpFilename}}), + ResponseBody = case TmpFilename of + undefined -> + Body; + _ -> + {file, TmpFilename} + end, + do_reply(From, StreamTo, ReqId, {ok, SCode, RespHeaders, ResponseBody}), cancel_timer(ReqTimer, {eat_message, {req_timedout, From}}), - State_1#state{tmp_file_name=undefined, tmp_file_fd=undefined}; + State_1; handle_response(#request{from=From, stream_to=StreamTo, req_id=ReqId}, #state{http_status_code=SCode, recvd_headers=RespHeaders, reply_buffer=RepBuf, transfer_encoding=TEnc, @@ -1193,7 +1232,14 @@ lists:foreach(fun(#request{from=From, stream_to=StreamTo, req_id=ReqId}) -> do_reply(From, StreamTo, ReqId, {error, Err}) end, ReqList). - + +fail_pipelined_requests(#state{reqs = Reqs, cur_req = CurReq} = State, Reply) -> + {_, Reqs_1} = queue:out(Reqs), + #request{from=From, stream_to=StreamTo, req_id=ReqId} = CurReq, + do_reply(From, StreamTo, ReqId, Reply), + do_error_reply(State#state{reqs = Reqs_1}, previous_request_failed). + + split_list_at(List, N) -> split_list_at(List, N, []). split_list_at([], _, Acc) -> @@ -1308,3 +1354,4 @@ to_lower(T, [H|Acc]); to_lower([], Acc) -> lists:reverse(Acc). + |
From: Chandru <cha...@us...> - 2008-02-07 12:02:21
|
Update of /cvsroot/jungerl/jungerl/lib/ibrowse In directory sc8-pr-cvs6.sourceforge.net:/tmp/cvs-serv1196 Modified Files: README vsn.mk Log Message: A mofidied version of a patch sent in by Ram Krishnan to enhance the save_response_to_file option Index: README =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ibrowse/README,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- README 19 Oct 2007 12:43:48 -0000 1.12 +++ README 7 Feb 2008 12:02:10 -0000 1.13 @@ -22,6 +22,12 @@ CONTRIBUTIONS & CHANGE HISTORY ============================== +07-02-2008 - Ram Krishnan (kriyative _at_ gmail dot com) sent a simple patch to + enable specifying the filename in the save_response_to_file option. + When testing the patch, I realised that my original implementation + of this feature was quite flaky and a lot of corner cases were + not covered. Fixed all of them. Thanks Ram! + 17-10-2007 - Matthew Reilly (matthew dot reilly _at_ sipphone dot com) sent a bug report and a fix. If the chunk trailer spans two TCP packets, then ibrowse fails to recognise that the chunked transfer Index: vsn.mk =================================================================== RCS file: /cvsroot/jungerl/jungerl/lib/ibrowse/vsn.mk,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- vsn.mk 19 Oct 2007 12:49:03 -0000 1.10 +++ vsn.mk 7 Feb 2008 12:02:11 -0000 1.11 @@ -1,2 +1,2 @@ -IBROWSE_VSN = 1.2.9 +IBROWSE_VSN = 1.3.0 |