Cannot submit valid form in FormFunction

I have a simple FormFunction like this:

FormFunction[{"expr" -> ToExpression}, HTTPRequestData[] &]


When I use CloudDeploy, it works as normal. But when I use SocketListen and GenerateHTTPResponse to establish a server, my Chrome seems have submitted no data as I can't Find it in the results of HTTPRequestData.

I've tried remote server(instead of local), GenerateHTTPResponse(instead of any really existing server), #expr &(instead of HTTPRequestData[] &), none of them works. If I use APIFunction as the backend and URLRead as the client, everything is OK.

What's missing for the submission compared to the WolframCloud one?

Here I provide a minimal server code. When I run this code on my VPS and click the submit button on my Chrome, nothing was submitted in fact.

#!/usr/bin/env wolframscript
Respond[socketMsg_Association] := Module[
{
client = socketMsg["SourceSocket"],
data = socketMsg["Data"],
request,
response
},
request = ImportString[data, "HTTPRequest"];
response = GenerateHTTPResponse[
URLDispatcher@{"" -> EvaluationService}
, request];
WriteString[
client,
ExportString[response, "HTTPResponse"]
];
Close@client
]
EvaluationService = FormFunction[
{"expr" -> <|"Interpreter" -> ToExpression, "Required"->False|>},
#expr &
];
SocketListen[{"0.0.0.0",8080},Respond]
Print@"Running..."
TaskWait@ZeroMQLinkPrivate\$AsyncState["Task"]

• What are you trying to do with the form? – kickert Jan 25 '20 at 17:07
• @kickert I just want to evaluate expressions via internet explorer etc.. – bcegkmqs23 Jan 26 '20 at 5:23
• @Kuba I've updated this question with a server code. The ToExpression usage is documented, here's a link: FormObject. In the "Details and Options", there's a tfun item listed below "Possible forms of type specifications are" – bcegkmqs23 Jan 28 '20 at 9:03
• Thanks for clarification, I was looking at Interpreter docs. btw, it boils down to the fact that HTTPRequest[...]["FormRules"] returns None. You could use this patch: requestFormRules = Rule @@@ Partition[#, 2] &@URLDecode@StringSplit[#, {"&", "="}] &@ StringTrim@FromCharacterCode[#["BodyBytes"], "UTF-8"] & but I am not sure how to apply it. – Kuba Jan 28 '20 at 10:38
• @Kuba This command can be effective if it works independently, I have a similar code written before. However, it's still confusing why FormFunction ignores submitted body data. I may go for the source code of GenerateHTTPResponse and FormFunction in the future. – bcegkmqs23 Jan 28 '20 at 13:25

As @Kuba had commented, ImportString[#, "HTTPRequest"]& does not turn POST parameters to rules. So the property "FormRules", which FormFunction utilizes, can't be generated.

Here is a function to finish this convertion when needed:

MakeFormRules[request_HTTPRequest] := With[
{
makeFormRules = <|
URLQueryDecode@StringTrim@FromCharacterCode[#, "UTF-8"]&
},
If[AssociationQ@makeFormRules@request["Body"], MapAt[makeFormRules, {2, "Body"}]@request, request]
]


Using it to process HTTPRequest received, the example code given in the question works.

request = MakeFormRules@ImportString[data, "HTTPRequest"];


It seems that WolframCloud use a function not provided in CloudObject(I didn't find it by Names[something]) but in its backend, which deals with this example and multipart/formdata etc.