1
$\begingroup$

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@ZeroMQLink`Private`$AsyncState["Task"]
$\endgroup$
  • $\begingroup$ What are you trying to do with the form? $\endgroup$ – kickert Jan 25 at 17:07
  • $\begingroup$ @kickert I just want to evaluate expressions via internet explorer etc.. $\endgroup$ – bcegkmqs23 Jan 26 at 5:23
  • $\begingroup$ @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" $\endgroup$ – bcegkmqs23 Jan 28 at 9:03
  • $\begingroup$ 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. $\endgroup$ – Kuba Jan 28 at 10:38
  • $\begingroup$ @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. $\endgroup$ – bcegkmqs23 Jan 28 at 13:25
2
$\begingroup$

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.

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.