How to do http POST in Mathematica?

In a post about automated image uploading Arnoud Buzing describes an undocumented and unsupported POST method. It looks like this:

 xml = Import[url, "XML", "RequestMethod" -> "POST", 
              "RequestParameters" -> {"key" -> key, "image" -> image}];

Note: at the time of this answer I was using V8. Since the arrival of URLFetch in V9 I believe URLFetch is the preferred method.


Use URLFetch in Mathematica 9.0.1.


Using the great example of Szabolcs from here, I implemented the following little function that solves my problem. You must give it a List of Rules, and it will send them to the hard-coded web-service endpoint inside. To test it, I implemented a little NodeJs server that reads the JSON body of a POST request, parses it, unparses it, and sends it back. So this is just a very expensive way of converting rules into JSON in MMA, checking their syntax in Node.Js, and sending them back to MMA to be decoded back into native rules.

bounceRules[requestRules_] :=
 Module[{
   requestJsonString,
   url, client, method,
   entity, responseCode, response,
   responseRules, responseExpression},
  JavaBlock[
   requestJsonString = ExportString[requestRules, "JSON"];
   url = "http://127.0.0.1:5000/bounce";
   client = JavaNew[
     "org.apache.commons.httpclient.HttpClient"];
   method = JavaNew[
     "org.apache.commons.httpclient.methods.PostMethod", url];
   entity = JavaNew[
     "org.apache.commons.httpclient.methods.StringRequestEntity",
     jsonString];
   method@setRequestEntity[entity];
   responseCode = client@executeMethod[method];
   If[responseCode === 200,
    (* then *)
    response = method@getResponseBodyAsString[];
    responseRules = ImportString[response, "JSON"];
    (* else *)
    Message[
     bounceRules::httperr,
     responseCode];
    $Failed
    ]]]

My main hangup, btw, was due to the fact that http://localhost inexplicably does not work. I get timeouts and exceptions and all manner of opaque torture from the java stack. Once I switched to http://127.0.0.1 everything just worked.