
Note: This class and file will be renamed into "xhttp..." in the near
feature, to prevent clashes with the old PEAR class.

http.php
ŻŻŻŻŻŻŻŻ
This script provides an easy to use "http_request" class ("http_query"
is an alias). You can contact forms or simply retrieve files with it.
Unlike fopen_wrappers, you get the response headers alongside and the
received file will be decompressed on-the-fly (it should also be faster
due to more supported compression methods).

There are some options you can set before starting the request. Most
important aspect is, that you can add form ->params[] one after the
other for GET and POST requests. You can also use a proxy or include
authentication passwords in the initially given url, and of course
inject or override a few ->headers[] when it makes sense.



usage
ŻŻŻŻŻ
It's really easy, you just have to take care to always give the method
parameter before the URL ("GET" or "POST" in most cases):

  <?example

      #-- prepare
      $query = new http_request("GET", "http://example.com/form.php");
      $query->params["q"] = "search-this-...";

      #-- do request
      $result = $query->go();

      #-- use result
      if ($result && ($result->status == 200)) {
         echo $result->content;
      }
  ?>

Note, that we could have included the "q" parameter simply appended to
the URL in such simple cases ("http://example.com/form.php?q=search-...").

For POST request you have to decide about the encoding format. There are
two options, the default is always urlencoding (like with GET requests):
  <?example 
      $query->type = "url";    // corresponds to "app/x-www-form-urlencoded"
  ?>
many bigger forms however require the MIME type for form-data:
  <?example 
      $query->type = "form";    // translates to "multipart/form-data"
  ?>

Any form variables you want to transport are simply appended to the URL
for GETs or "url"-coded requests, but you could use the $query->params[]
array as well.

PUT / POST requests are initiated likewise. But you could also just assign
a string blob to $query->params, if that's to be transfered as content.
(If the remote app can deal with / expects that. Of if you already have
encoded eveything into a valid form request).

For adding upload-files to a normal POST request, just do this however:
  <?example
      $query->params["fileformname"] = array(
         "filename" => "original-name.zip",
         "type" => "application/octet-stream",
         "content" => "$READ_FROM_FILE_DATA...",
      );
  // or
      $query->params["2nd_file"] = array(
         "ct" => "x.ml/my-format",
         "name" => "../../where/is/it/from.txt",
         "data" => file_get_contents(".../from.txt"),
      );
  ?>
"body" is a third alias for the "content" field here. If you don't set
the "type" or "ct" flag it will get "application/octet-stream" per default
(this is a good default). You could simply load the "ext/mime" script to
have the best possible MIME type here.



     start an request
     ŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻŻ
     Use the ->go() method to start a prepared HTTP request. The only
     alias existing today is ->start(); simply derive or edit this class
     to add your preferred name for this likewise (->do() cannot be used
     as it is a PHP reserved word, sorry ;)

     There are two options to ->go(), the first $force will override a few
     problems, and with the second ($asis) set to 1 or true, you won't get
     a result object, but the plain HTTP response blob (headers and response
     body as one large string variable).



     authentication
     ŻŻŻŻŻŻŻŻŻŻŻŻŻŻ
     If the remote site requires authentification, you would simply give
     this within the URL:
      <?example
         $query = new http_request("GET", "http://user:passw@example.com/...");
           // or later:
         $query->setURL("http://username:pw2@server.../")
           // or even:
         $query->url = "http://name:password@localhost/form.php";
      ?>



     proxy
     ŻŻŻŻŻ
     You can also acccess a form or remote file using a proxy server easily,
     just follow this:
      <?example
         $query = new http_request("PUT", "...");
         $query->proxy = "http://servername.proxy.org:3219/";
           // ...
         $result = $query->go();
      ?>
     You could also give a password or username for your proxy server, if
     you need it (works the same as for above).




reponses
ŻŻŻŻŻŻŻŻ
The $result value from the above examples should normally be an object,
it will be a scalar (false) only if something went really wrong.

It will have at least a ->status field, which is typically 200 for
succeeded requests. Everything above 500 means an server error, values
above 400 a transport and request error (= we did something wrong) and
a 300 response status means a redirection was issued.

For fulfilled requests you can access the returned file/data simply as
"$result->content" or "$result->body" or even "$result->data" (two aliases
again).

You will also have a "$result->headers[]" array, which will hold all
response HTTP headers in normalized form. Typically this means:
  <?example
      echo $result->headers["Content-Type"] . "\n";
      echo $result->headers["Date"] . "\n";
      echo $result->headers["Last-Modified"] . "\n";
      echo $result->headers["Content-Length"] . "\n";
      echo $result->headers["Etag"] . "\n";    // (beware of the lcased "t" !)
      echo $result->headers["Content-Encoding"] . "\n";
      ...
      print_r($result->headers);  // much better here ;)
  ?>
[[ Elsewhere the field names would be completely lowercased or fully
uppercase, we have CamelCase here, with the hyphens still in of course. ]]

Please note, that a known "Content-Encoding" was already removed from the
received ->content. And there is also a more correct "$result->len" and a
"$result->type" shorthand.

A few response types are understand as application data, and in this case
you can call the $result->decode() function and get a PHP variable/array
from the body.



     redirects
     ŻŻŻŻŻŻŻŻŻ
     If you expect HTTP redirects (->status codes from 300 till 375), then
     the default settings are ok for you, many will automatically be catched
     and the form data or file request will succeed at the replied URL.

     To tack/catch these cases yourself, simply disable that behaviour with:
      <?example
         $query->active_client = 0;
      ?>



PHP-RPC
ŻŻŻŻŻŻŻ
Not yet!  But this is probably what it will look like:

  If you control both ends of the Wire, you shouldn't use the slow and
  buggy (not everything works with everything else) XML-RPC protocol for
  calling remote functions, but instead use the high speed PHP serialize
  encoding to transfer data.

  The "http_request" class can natively encode values as such. The MIME
  type "application/vnd.php.serialized" has been registered explicitely
  for this purpose (as alternative to "multipart/form-data" encoding,
  and it is type-safe as opposed to the "/x-www-form-urlencoded" format).
  Perl and JS implementations exist (probably also one for Python), so
  plattform-independence should be given.

  PHP-RPC shall inherit (not yet negotiated) some structure from the old
  XML-RPC protocol. That is, a few names are identical. If you start an
  request you would therefore do following:

<?php

    function phprpc($server, $function, $args=array()) {

       #-- init
       $query = new http_request("POST", $server);

       #-- set content
       $query->type = "php";  // here corresponds to "app/vnd.php.serialized"
       $query->params
         = array(
              "method" => $function,
              "params" => $args,
           );

       #-- start
       $result = $query->go();
       if ($result && ($result->status == 200)) {

          $r = $result->decode();
          if ($good = $r["result"]) {
             return($good);
          }
          return($r);
       }
    }
?>

  You of course need a server part to make use of this. Simply try the
  "ext/phprequest", in which case you would do the following:

<?php

   include("ext/phprequest.php")
   if (count($_POST) && ($method = $_POST["method"])
   and ($params = $_POST["params"]))
   {
      #-- call known/registered functions
      $method = strtolower($method);
      if ($method == "my.func") {
         $r = call_user_func_array("my_func", $params);
      }
      elseif ($method == "system.time") {
         $r = time();
      }
      elseif ($method == "sytem.listmethods") {
         $r = get_defined_functions();
         $r = $r["user"];
      }

      #-- if succeeded
      if ($r) { 
         header("Content-Type: application/vnd.php.serialized");
         header("Content-Encoding: deflate");
         $r = array("result" => $r);
         die(gzdeflate(serialize($r));
      }
   }

   #-- your normal script can go on here
   //...
?>

  You can inject this into anywhere as it only engages, if a PHP-RPC
  request was detected. 



