Message Boards Message Boards

HTTPHandling`WebServer missing HTTP request body ?

GROUPS:

Though the HTTPHandling paclet is not yet documented, I got excited by the video (from C. Barbieri & R. Di Virgilio) and I tried a test ride. I wanted to prototype a local server supporting hot reload. However I faced a really strange behavior.

The main function WebServer when used with URLDispatcher and APIFunction does not behave as expected. I will give a self-contained example below.

Example

We define an APIFunction which returns the body of the HTTP request payload after importing it as a "JSON" string. We also create a test "JSON" string named body.

post$Test = APIFunction[{},
               Block[{s},
                s = HTTPRequestData[{"Method", "Headers", "Body"}];
                 ImportString[s[[3]],"JSON"]
                  ]&
                ];
body = ExportString[{"User-1"->{"Name"->"Rob","Age"->28},"User-2"->{"Name"->"Bob","Age" ->32}},"JSON"];

Now we use URLDispatcher to deploy the API to cloud. Everything works as usual and we can access the body of the POST request.

works=
  CloudDeploy[
    URLDispatcher[{"/Test" -> post$Test}],
    "try",
    Permissions -> "Public"
    ][[1]];
HTTPRequest[
  URLBuild@{works, "Test"},
  <|"Method" -> "POST", "Headers" -> {"accept" -> "*/*", "content-type" -> "application/json"},
   "Body" -> body|>
  ] // URLExecute
{"User-1" -> {"Name" -> "Rob", "Age" -> 28}, "User-2" -> {"Name" -> "Bob", "Age" -> 32}}

However the same API fails to catch the body part of the POST request and throws an error.

serv =
  HTTPHandling`StartWebServer[URLDispatcher[{"/Test" -> post$Test}]];
HTTPRequest[
  "http://localhost:7000/Test",
  <|"Method" -> "POST","Headers" -> {"accept" -> "*/*", "content-type" -> "application/json"},
   "Body" -> body|>
  ] // URLExecute
ImportString::string: First argument None is not a string.
ImportString[None, "JSON"]

Looking at the "Main.m" file suggests that the "AsyncHandler" of the WebServer is working with a data where the body part of the HTTP request seems to be already missing. Probably someone from the developers or experts can shade some light here.

FileNameJoin@{
   PacletFind["HTTPHandling"][[1]]["Location"],
   "Main.m"
   } // SystemOpen

Question

  • Is there a possible workaround of the above problem in the HTTPHandling context?
  • If there is a workaround, can one also POST a file (pdf,jpg,.. etc.) or other binary data and access that data from the HTTPRequestData via the APIFunction construct like above?
POSTED BY: rob imran
Answer
3 months ago

Group Abstract Group Abstract