2
$\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$
7
  • $\begingroup$ What are you trying to do with the form? $\endgroup$
    – kickert
    Jan 25, 2020 at 17:07
  • $\begingroup$ @kickert I just want to evaluate expressions via internet explorer etc.. $\endgroup$
    – bcegkmqs23
    Jan 26, 2020 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, 2020 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, 2020 at 10:38
  • 1
    $\begingroup$ It does not work because of HttpRequest generated from ImportString. Form values are missing even though they are in the body. I already reported this. $\endgroup$
    – Kuba
    Jan 28, 2020 at 16:25

1 Answer 1

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.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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