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?