From 2271a3c84c5b7410a72ac6d2de19db7a4df3f814 Mon Sep 17 00:00:00 2001
From: "Mirar (Pontus Hagland)" <pike@sort.mirar.org>
Date: Sat, 15 Feb 2003 09:59:39 +0100
Subject: [PATCH] Asynchroneous methods added

Rev: lib/modules/Protocols.pmod/HTTP.pmod/Session.pike:1.2
---
 .gitattributes                                |   1 +
 .../Protocols.pmod/HTTP.pmod/Session.pike     | 267 +++++++++++++++---
 2 files changed, 224 insertions(+), 44 deletions(-)

diff --git a/.gitattributes b/.gitattributes
index c12cb50b3a..29379f62e5 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -138,6 +138,7 @@ testfont binary
 /lib/modules/Pike.pmod foreign_ident
 /lib/modules/Protocols.pmod/DNS.pmod foreign_ident
 /lib/modules/Protocols.pmod/HTTP.pmod/Query.pike foreign_ident
+/lib/modules/Protocols.pmod/HTTP.pmod/Session.pike foreign_ident
 /lib/modules/Protocols.pmod/IMAP.pmod/imap_server.pike foreign_ident
 /lib/modules/Protocols.pmod/IMAP.pmod/requests.pmod foreign_ident
 /lib/modules/Protocols.pmod/IRC.pmod/Requests.pmod foreign_ident
diff --git a/lib/modules/Protocols.pmod/HTTP.pmod/Session.pike b/lib/modules/Protocols.pmod/HTTP.pmod/Session.pike
index 96707d0a54..844c009ade 100644
--- a/lib/modules/Protocols.pmod/HTTP.pmod/Session.pike
+++ b/lib/modules/Protocols.pmod/HTTP.pmod/Session.pike
@@ -1,7 +1,24 @@
 #pike __REAL_VERSION__
 
+// $Id: Session.pike,v 1.2 2003/02/15 08:59:39 mirar Exp $
+
 import Protocols.HTTP;
 
+//!	The number of redirects to follow, if any.
+//!	This is the default to the created Request objects.
+//!
+//!	A redirect automatically turns into a GET request,
+//!	and all header, query, post or put information is dropped.
+//!
+//!	Default is 20 redirects. A negative number will mean infinity.
+//! @bugs
+//!	Loops will currently not be detected, only the limit
+//!	works to stop loops.
+//! @seealso
+//!	@[Request.follow_redirects]
+
+int follow_redirects=20;
+
 class Request
 {
 //!	Raw connection object
@@ -11,18 +28,19 @@ class Request
 //!	This will update according to followed redirects.
    Standards.URI url_requested;
 
-//!	flags to follow redirects; if set,
+//!	Number of redirects to follow;
 //!	the request will perform another request if the 
 //!	HTTP answer is a 3xx redirect.
-//!	Default is to follow 50 redirects.
+//!	Default from the parent @[Session.follow_redirects].
 //!
 //!	A redirect automatically turns into a GET request,
 //!	and all header, query, post or put information is dropped.
-//! @known_bugs
+//! @bugs
 //!	Loops will currently not be detected, only the limit
 //!	works to stop loops.
 
-   int follow_redirects=50;
+   int follow_redirects= // parent
+      function_object(object_program(this_object()))->follow_redirects;
 
 //!	Cookie callback. When a request is performed,
 //!	the result is checked for cookie changes and
@@ -239,7 +257,7 @@ class Request
 	  con->headers->location && follow_redirects)
       {
 	 Standards.URI loc=
-	    Standards.URI(url_requested,con->headers->location);
+	    Standards.URI(con->headers->location,url_requested);
 
 	 if(loc->scheme=="http" || loc->scheme=="https")
 	 {
@@ -288,6 +306,16 @@ class Request
       return con->ok;
    }
 
+   int(0..999) status()
+   {
+      return con->status;
+   }
+
+   string status_desc()
+   {
+      return con->status_desc;
+   }
+
 // ----------------
 // cookie calculations
 
@@ -544,10 +572,59 @@ Request do_method(string method,
    return p;
 }
 
-//! @decl Request get_url(string|Standards.URI url)
+// Request|array(string) generic_do_method(
+//    string method,
+//    string mode,
+//    string|Standards.URI url,
+//    string|mapping|function ...misc)
+// {
+//    array args;
+//    mapping query_variables=0;
+//    mapping extra_headers=0;
+//    string data=0;
+// 
+//    misc+=({0,0,0,0});
+// 
+//    switch (lower_case(method))
+//    {
+//       case "get":
+//       case "delete":
+// 	 query_variables=misc[0];
+// 	 misc=misc[1..];
+// 	 break;
+//       case "put":
+// 	 query_variables=misc[0];
+// 	 data=misc[1];
+// 	 if (data && !stringp(data))
+// 	    error("Bad argument 5 to Session.put*, expected string\n");
+// 	 misc=misc[2..];
+// 	 break;
+//       case "post":
+// 	 if (!mappingp(misc[0]))
+// 	    error("Bad argument 4 to Session.put*, expected mapping\n");
+// 	 data=http_encode_query(misc[0]);
+// 	 extra_headers=(["content-type":"application/x-www-form-urlencoded"]);
+// 	 break;
+//       default:
+// 	 error("unknown HTTP method %O (expected get, post, put or delete)\n");
+//    }
+//    if (query_variables && !mappingp(query_variables))
+//       error("Bad argument 4 to Session."+method+"*, "
+// 	    "expected mapping or void\n");
+// 
+//    args=p->prepare_method(upper_case(method),url,query_variables,
+// 			  extra_headers,data);
+// }
+
 //! @decl Request get_url(string|Standards.URI url, @
-//!                       mapping query_variables)
-//! 	Sends a HTTP GET request to the server in the URL
+//!                       void|mapping query_variables)
+//! @decl Request post_url(string|Standards.URI url, @
+//!                        mapping query_variables)
+//! @decl Request put_url(string|Standards.URI url,string file, @
+//!                       void|mapping query_variables)
+//! @decl Request delete_url(string|Standards.URI url, @
+//!                          void|mapping query_variables)
+//! 	Sends a HTTP GET, POST, PUT or DELETE request to the server in the URL
 //!	and returns the created and initialized @[Request] object.
 //!	0 is returned upon failure. 
 //!
@@ -557,13 +634,6 @@ Request get_url(string|Standards.URI url,
    return do_method("GET", url, query_variables);
 }
 
-//! @decl Request put_url(string|Standards.URI url)
-//! @decl Request put_url(string|Standards.URI url,string file)
-//! @decl Request put_url(string|Standards.URI url,string file, @
-//!                       mapping query_variables)
-//! 	Sends a HTTP PUT request to the server in the URL
-//!	and returns the created and initialized @[Request] object.
-//!	0 is returned upon failure. 
 Request put_url(string|Standards.URI url,
 		void|string file,
 		void|mapping query_variables)
@@ -571,29 +641,37 @@ Request put_url(string|Standards.URI url,
    return do_method("PUT", url, query_variables, file);
 }
 
-//! @decl Request delete_url(string|Standards.URI url)
-//! @decl Request delete_url(string|Standards.URI url, @
-//!                          mapping query_variables)
-//! 	Sends a HTTP DELETE request to the server in the URL
-//!	and returns the created and initialized @[Request] object.
-//!	0 is returned upon failure. 
 Request delete_url(string|Standards.URI url,
-		   void|mapping query_variables,
-		   void|mapping request_headers,
-		   void|Request con)
+		   void|mapping query_variables)
 {
    return do_method("DELETE", url, query_variables);
 }
 
+Request post_url(string|Standards.URI url,
+		 mapping query_variables)
+{
+   return do_method("POST", url, 0,
+		    http_encode_query(query_variables));
+}
+
+
 //! @decl array(string) get_url_nice(string|Standards.URI url, @
 //!                                  mapping query_variables)
 //! @decl string get_url_data(string|Standards.URI url, @
 //!                           mapping query_variables)
+//! @decl array(string) post_url_nice(string|Standards.URI url, @
+//!                                   mapping query_variables)
+//! @decl string post_url_data(string|Standards.URI url, @
+//!                            mapping query_variables)
 //!	Returns an array of @tt{({content_type,data})@} and just the data
 //!	string respective, 
 //!	after calling the requested server for the information.
 //!	0 is returned upon failure.
 //!
+//! 	post* is similar to the @[get_url()] class of functions,
+//!	except that the query variables is sent as a POST request instead
+//!	of as a GET.
+//!
 
 array(string) get_url_nice(string|Standards.URI url,
 			   void|mapping query_variables)
@@ -603,30 +681,12 @@ array(string) get_url_nice(string|Standards.URI url,
 }
 
 string get_url_data(string|Standards.URI url,
-		    void|mapping query_variables,
-		    void|mapping request_headers,
-		    void|Request con)
+		    void|mapping query_variables)
 {
-   Request z = get_url(url, query_variables, request_headers, con);
+   Request z = get_url(url, query_variables);
    return z && z->data();
 }
 
-//! @decl array(string) post_url_nice(string|Standards.URI url, @
-//!                                   mapping query_variables)
-//! @decl string post_url_data(string|Standards.URI url, @
-//!                            mapping query_variables)
-//! @decl object(Request) post_url(string|Standards.URI url, @
-//!                                             mapping query_variables)
-//! 	Similar to the @[get_url()] class of functions, except that the
-//!	query variables is sent as a POST request instead of as a GET.
-//!
-
-Request post_url(string|Standards.URI url,
-		 mapping query_variables)
-{
-   return do_method("POST", url, 0,
-		    http_encode_query(query_variables));
-}
 
 array(string) post_url_nice(string|Standards.URI url,
 			    mapping query_variables)
@@ -642,3 +702,122 @@ string post_url_data(string|Standards.URI url,
    return z && z->data();
 }
 
+// ================================================================
+// async operation
+
+Request async_do_method(string method,
+			string url,
+			void|mapping query_variables,
+			void|string data,
+			function callback_headers_ok,
+			function callback_data_ok,
+			function callback_fail,
+			array callback_arguments)
+{
+   mapping extra_headers=0;
+   if (method=="POST")
+      extra_headers=(["content-type":"application/x-www-form-urlencoded"]);
+   
+   Request p=Request();
+   p->set_callbacks(callback_headers_ok,
+		    callback_data_ok,
+		    callback_fail,
+		    p,@callback_arguments);
+   p->do_async(p->prepare_method(method,url,query_variables,
+				 extra_headers,data));
+   return p;
+}
+
+
+//! @decl Request async_get_url(string|Standards.URI url,
+//! 			    void|mapping query_variables,
+//! 			    function callback_headers_ok,
+//! 			    function callback_data_ok,
+//! 			    function callback_fail,
+//! 			    mixed... callback_arguments);
+//! @decl Request async_put_url(string|Standards.URI url,
+//! 			    void|string file,
+//! 			    void|mapping query_variables,
+//! 			    function callback_headers_ok,
+//! 			    function callback_data_ok,
+//! 			    function callback_fail,
+//! 			    mixed... callback_arguments);
+//! @decl Request async_delete_url(string|Standards.URI url,
+//! 			       void|mapping query_variables,
+//! 			       function callback_headers_ok,
+//! 			       function callback_data_ok,
+//! 			       function callback_fail,
+//! 			       mixed... callback_arguments);
+//! @decl Request async_post_url(string|Standards.URI url,
+//! 			     mapping query_variables,
+//! 			     function callback_headers_ok,
+//! 			     function callback_data_ok,
+//! 			     function callback_fail,
+//! 			     mixed... callback_arguments);
+//!
+//! 	Sends a HTTP GET, POST, PUT or DELETE request to the server in
+//!     the URL asynchroneously, and call the corresponding callbacks
+//!	when result arrives (or not). The callbacks will receive 
+//!	the created Request object as first argument, then 
+//!	the given @[callback_arguments], if any.
+//!	
+//!	@[callback_headers_ok] is called when the HTTP request has received
+//!	headers. 
+//!
+//!	@[callback_data_ok] is called when the HTTP request has been 
+//!	received completely, data and all.
+//!
+//!	@[callback_fail] is called when the HTTP request has failed,
+//!	on a TCP/IP or DNS level, or has recieved a forced timeout.
+//!
+//!	The created Request object is returned.
+
+Request async_get_url(string|Standards.URI url,
+		      void|mapping query_variables,
+		      function callback_headers_ok,
+		      function callback_data_ok,
+		      function callback_fail,
+		      mixed ...callback_arguments)
+{
+   return async_do_method("GET", url, query_variables,0,
+			  callback_headers_ok,callback_data_ok,
+			  callback_fail,callback_arguments);
+}
+
+Request async_put_url(string|Standards.URI url,
+		      void|string file,
+		      void|mapping query_variables,
+		      function callback_headers_ok,
+		      function callback_data_ok,
+		      function callback_fail,
+		      mixed ...callback_arguments)
+{
+   return async_do_method("PUT", url, query_variables, file,
+			  callback_headers_ok,callback_data_ok,
+			  callback_fail,callback_arguments);
+}
+
+Request async_delete_url(string|Standards.URI url,
+			 void|mapping query_variables,
+			 function callback_headers_ok,
+			 function callback_data_ok,
+			 function callback_fail,
+			 mixed ...callback_arguments)
+{
+   return async_do_method("DELETE", url, query_variables, 0,
+			  callback_headers_ok,callback_data_ok,
+			  callback_fail,callback_arguments);
+}
+
+Request async_post_url(string|Standards.URI url,
+		       mapping query_variables,
+		       function callback_headers_ok,
+		       function callback_data_ok,
+		       function callback_fail,
+		       mixed ...callback_arguments)
+{
+   return async_do_method("POST", url, 0,
+			  http_encode_query(query_variables),
+			  callback_headers_ok,callback_data_ok,
+			  callback_fail,callback_arguments);
+}
-- 
GitLab