Can't Receive POST form data from UnityEngine Game Client in http-functions post call

Hi everyone,

As a bit of background. I’m a game developer with a bit of web development experience. I’m using our company’s Wix site as a backend for storing information about our players and their stats in one of our games.

I’ve been trying to set up an account/login system for our game that can be accessed directly from our client with username and password functionality.

So far I’ve been using get functions in our http-functions call because I haven’t been able to get a Post or a Put call to work. Our needs for some particular functions mean I can’t use a GET call in this case.

I think it must be an issue on the web server’s end (maybe something I’m doing wrong?) because I tested my code from our client application with my own personal web server using
a PHP backend and I was able to access the POST data from the client form just fine.

Maybe I’m just unaware of how to access POST data from the request object but from what I’ve read in the documentation regarding POST it should be in the body portion of the request. However, when I make the call from our game client and output the entire request object the body is empty and there is no sign of my POST form data or anything.

Is there a second object parameter that my post function needs? How can I access data sent to this function via POST or a form? (to be clear, this data is not coming from our wix site it’s coming from an external client). Maybe I need to change the content-type in the header of the request somehow?

Here is a sample of my testing code:

Game client side Code in Unity (2020.1.14f1) (C#):

public static IEnumerator RegisterTest(string username, string password)
    {
        string url = $"www.OurCompanyWixSite. ca/_functions/Register";
        WWWForm form = new WWWForm();
        form.AddField("username", username);
        form.AddField("password", password);

        using (UnityWebRequest webRequest = UnityWebRequest.Post(url, form))
        {
            yield return webRequest.SendWebRequest();

            if (webRequest.isNetworkError || webRequest.isHttpError)
            {
                Debug.LogError(webRequest.error);
                Debug.Log(webRequest.downloadHandler.text);
            }
            else
            {
                Debug.Log(webRequest.downloadHandler.text);
            }
        }

        ProceedToNextWebCall();
    }

The code from http-functions (javascript):

import {ok , notFound, serverError } from 'wix-http-functions';

//...

export function post_Register(request){
  {
        let options = {
            "headers":{
                "Content-Type": "application/json"
            }
        };
        options.body = request;     

        return ok(options);
    }
}

the response is this the entire request object (I had to modify any links in here to post) is this (excluding a few details in case they are sensitive):

{
   "functionName":"Register",
   "path":[
      
   ],
   "url":"http: //OurCompanyWixSite/_functions/Register",
   "baseUrl":"http: //OurCompanyWixSite/_functions",
   "method":"POST",
   "body":{
      
   },
   "headers":{
      "host":"www.OurCompanyWixSite. ca",
      "user-agent":"UnityPlayer/2020.1.14f1 (UnityWebRequest/1.0, libcurl/7.52.0-DEV)",
      "transfer-encoding":"chunked",
      "accept":"*/*",
      "accept-encoding":"identity",
      "authorization": // an authorization ID is here,
      "cid":"",
      "content-type":"application/x-www-form-urlencoded",
      "geoip_country_code":"CA",
      "geoip_country_code3":"CAN",
      "identities":"{\"identificationData\":{},\"signedToken\":\"/* A signed token ID is here */"}",
      "requesturl":"_functions/Register",
      "via":"1.1 google",
      "x-cloud-trace-context": //Some ID is here,
      "x-envoy-expected-rq-timeout-ms":"120000",
      "x-forwarded-for": // 2 IPs are here,
      "x-forwarded-proto":"http",
      "x-newrelic-id": //Some ID is here,
      "x-newrelic-transaction": //Some ID is here,
      "x-original-authority":"com .wixpress.wixcode.wix-code-functions-public-dispatcher",
      "x-real-ip": //real-ip is here,
      "x-request-id": //request ID is here,
      "x-unity-version":"2020.1.14f1",
      "x-wix-aid": //aid ID is here,
      "x-wix-artifact-id":"com .wixpress.wixcode.wix-code-functions-public-dispatcher",
      "x-wix-authorization": //authorization is here
      "x-wix-code-elementory-experiments":"{\"specs.wixCode.replaceBabelWithSwc\":\"true\"}",
      "x-wix-code-forwarded-url":"http://www.OurCompanyWixSite. ca/_functions/Register",
      "x-wix-code-instance-id": // instance ID is here,
      "x-wix-code-owner-id": // Wix owner ID is here,
      "x-wix-code-public-url":"http://www.OurCompanyWixSite. ca/_functions/Register",
      "x-wix-country-code":"CA",
      "x-wix-country-code3":"CAN",
      "x-wix-data-tenant-id": //tenant ID is here,
      "x-wix-ddos-entry-point":"nane1",
      "x-wix-diag-ctx": //An ID is here
      "x-wix-forwarded-url":"http://www.OurCompanyWixSite. ca/_functions/Register",
      "x-wix-google-ccm":"1",
      "x-wix-grid-app-id"://app id is here,
      "x-wix-host-rewrite"://company website is here,
      "x-wix-instance-id": //instance ID is here,
      "x-wix-locale":"{\"locale\":\"en\"}",
      "x-wix-meta-site-id": //Meta site ID is here,
      "x-wix-region-code":"ON",
      "x-wix-request-id"://Request ID is here,
      "x-wix-route-account-settings-server":"rollout",
      "x-wix-route-funnel-builder-service":"rollout",
      "x-wix-route-seating-public":"rollout",
      "x-wix-server-identity": //Server Identity is here
      "x-wix-signed-token"://Token ID is here
      "x-wix-site-revision":"1546",
      "x-wix-use-cloud-data":"true",
      "x-wix-use-data-edm-module":"false",
      "x-wix-use-dstore":"true",
      "x-wix-use-platformized-data-api":"false",
      "x-wix-use-telemetry-logs":"false",
      "x-wix-user-agent":"{\"ua\":\"Other\",\"os\":\"Unknown\",\"deviceClass\":\"Other\",\"engine\":\"Other\"}",
      "x-wix-user-agent-info":"{\"ua\":\"Other\",\"os\":\"Unknown\",\"deviceClass\":\"Other\",\"engine\":\"Other\",\"uaDetails\":{\"name\":\"\"},\"osDetails\":{\"name\":\"\"},\"excludedSafariOrIOS\":false}",
      "x-wix-view-mode":"Site"
   },
   "ip": //IP is here
}

The body portion of the request object seems to be empty.

If anyone has any idea what might be my issue I would greatly appreciate any help. If more information is needed please let me know! Maybe there is an npm package I could use instead if this doesn’t work?

Thank you!

I don’t see a problem on your wix side code (assuming you imported the ok function).
Have you tried it on Postman or other tool?
Are you getting 200 just without the body or something else?

(I am indeed importing the ok function. I forgot to include it in my code snippet since it was at the top of the file.)

I just tried on Postman making a Post Request. I get back a Status 200, but it seems there is nothing in the request.body using Postman either.

I tried with just some dummy data to see if it would return it, and sending it as:
form-data,
x-www-form-urlencoded,
raw (json)
raw(text)

The content type was changing appropriately in the request header each time, but each time I had an empty request.body.

Here are some screenshots of my tests. Maybe I’m doing something wrong?

form-data:

x-www-form-urlencoded:

Raw (JSON):

I see what you’re talking about.
Well, I don’t know the reason for that and what’s going on under the hood.
Is it really important to you to return the request body?
Anyway you can do something like:

import {ok , notFound, serverError } from 'wix-http-functions';
//...
export async function post_Register(request){
  {
        let options = {
            "headers":{
                "Content-Type": "application/json"
            }
        };
 options.body = {request, body: await request.body.json()};
   return ok(options);
}

And you’ll get:

{
"request": {/*all the request details except the body*/},
"body": {/*body value*/}
}

Oh I am just returning the request just for testing purposes to make sure my POST form data is being sent through. I’ll need it to proceed with the next portion of my work.

I’ll give your suggestion a try. Thank you.

I’m not mistaken in assuming that when a standard POST request is normally sent that the form-data is in the request.body right? I just assumed that based on the Velo example of Post() in the documentation.

Right.

So I got it working. I am able to send data from unity and postman to my wix site via the http-functions and I just wanted to post an update for the record in case anyone has this issue or something similar.

I tried the code that J.D. suggested but it wasn’t working. I don’t think the http-functions will export and allow an async function to be called via visiting the URL that the function lives it (but correct me if I’m wrong, this is just based on what I experienced), BUT it did lead me on the right track to finding a solution.

My code on the Wix Side ended up looking like this (there is probably a much cleaner and better way to do it but my web dev skills are not incredibly great):

export function post_Register(request)
{
        let options = {
            "headers":{
                "Content-Type": "application/json"
            }
        };

        let waitForTheBody = async function waitForBody(request){   
            var postData = {message: "Success", body: await request.body.json() };
            options.body = postData;               
        }
        
        return waitForTheBody(request).then(()=>{           
            return ok(options);
        }).catch(()=>{
            options.body = "FAILED";
            return ok(options);
        })   
}

So this code just echos back the Post Data (obviously I’m going to be doing stuff with it but I just wanted to confirm I could send it first). The only issue I ran into was that this only works if the Post data is sent as “raw” data. In postman I was only able to get a proper response by sending raw json:

using any other options (form-data or x-www-form-urlencoded) does not work. It does return a status code of 200 but the resulting message is “FAILED” as my code above outputs on the catch.

I also had to modify my code on the clientside in Unity (C#) to this:

public static IEnumerator RegisterTest(string username, string password)
    {
        string url = $"www.ourcompanywebsite.ca/_functions/Register";

        Dictionary<string, string> data = new Dictionary<string, string>()
        {
            { "username", username },
            { "password", password }
        };

        string jsonData = JsonConvert.SerializeObject(data);

        using (UnityWebRequest webRequest = UnityWebRequest.Put(url, jsonData))
        {
            webRequest.method = UnityWebRequest.kHttpVerbPOST;
            webRequest.SetRequestHeader("Content-Type", "application/json");
            webRequest.SetRequestHeader("Accept", "application/json");

            yield return webRequest.SendWebRequest();

            if (webRequest.isNetworkError || webRequest.isHttpError)
            {
                Debug.LogError(webRequest.error);
                Debug.Log(webRequest.downloadHandler.text);
            }
            else
            {
                Debug.Log(webRequest.downloadHandler.text);
            }
        }

        ProceedToNextWebCall();
    }

The trick here is to use a Put Webrequest so you can pass in raw Json data (you can’t do that with Unity’s Post). And then before it is sent change the webRequest.method to UnityWebRequest.kHttpVerbPOST, so it sends it as a post request. Really hacky but seems to work. I also set the RequestHeaders to use JSON. (FTR: I am using Newtonsoft’s Json.net to do my json here)

You could also probably change the code on Wix’s side to be a put request but I wanted to keep mine as post.

I found help for the unity side of the code here:

I want to say again thank you for the help J.D. I owe you one! It managed to set me on the right path!

You’re welcome (by the way, I tried my code and it did work for me).

@jonatandor35 It was probably something I did on my end then. That’s good to know though incase anyone comes across this post.