javascriptc#unity-game-enginevercel

UnityWebRequest.Put doesn't send JSON string


I'm looking to make a PUT or POST request to an API I've deployed to Vercel built with NEXT JS. It does other things besides being an API but that's not important...

So, I have a Unity Project where I would like to log the time that my player completed the level they're on. Originally I wanted to use Firebase but discovered that I can't as the Windows Unity builds don't support it so I ended up just making an API that send the Data to MongoDB and does some other stuff, again not important.

So getting to the guts of the problem:

I have this IEnumerator to send the request:

IEnumerator logPlayerTime()
{
    string url = "http://some-vercel-cloud-function/api/new";
    var requestBody = new PlayerRequestBody();
    requestBody.firstName = "John";
    requestBody.lastName = "Doe";
    requestBody.email = "email@email.com";
    requestBody.marketing = false;
    requestBody.time = 200000;  // this actually come from somewhere else but for now this is fine

    string json = JsonUtility.ToJson(requestBody);

    UnityWebRequest request = UnityWebRequest.Put(url, json);
    request.SetRequestHeader("Content-Type", "application/json");
    request.SetRequestHeader("Accept", "*/*");
    request.SetRequestHeader("Accept-Encoding", "gzip, deflate, br");
    request.SetRequestHeader("Connection", "keep-alive");
    request.useHttpContinue = false;
    yield return request.SendWebRequest();

    if (request.result != UnityWebRequest.Result.Success)
    {
        Debug.Log(request.error);
    }
    else
    {
        Debug.Log("Time Logged! " + json);
    }
}

According to the Docs I should have two arguments, the first being my URL and the second Being my Data.

As for the JSON I want to send I made this struct

[Serializable]
private struct PlayerRequestBody
{
    public string firstName;
    public string lastName;
    public string email;
    public bool marketing;
    public float time;
}

Then, I'm using JsonUtiltiy.ToJson to turn my json variable into a JSON string, which seems to work.

All of this said, no matter what I change in the request, even typing the JSON string out manually escaped. It just sends a request body of an empty JSON object like this:

{}

So if we take a look at what the API receives the logs look like this:

[PUT] /api/new    01:44:25:13    {}

I'm sure it's something small but I just don't have enough experience with Unity or C# to find the issue (and I want to go to bed).

As for how this gets called, In one of my Scripts that manages the game I have a handler method that is subscribed to GameState changes, so when my GameState === GameState.Victory then I would run the handler. So the code for that, with bits removed for readability looks like this:

// ...
private void Awake()
{
    GameManager.OnGameStateChanged += GameManager_OnGameStateChanged;
}
// ...
private void GameManager_OnGameStateChanged(GameState state)
{
    
    if (state == GameState.Victory)
    {
        handleVictory();
    }

}

That handleVictory method just runs StartCoroutine on the IEnumerator at the moment


Solution

  • You need to add a trailing / to the url, so your url should be:

    string url = "http://some-vercel-cloud-function/api/new/";