Home > Blockchain >  Posting Json from Unity to Node server reads incorrectly
Posting Json from Unity to Node server reads incorrectly

Time:11-01

I am trying to connect my Unity game to my web server. I connect to the server fine with a vue app and also tested the endpoints in Postman, which all work great. However, when I send the JSON from Unity with the same information, it looks the same when I console out the req.body in my server route. Though when I get the length of the email, they are different. [email protected] has a length of 13, but when I send with Unity it has a length of 14. It always adds an extra character (length).

LoginData.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[Serializable]
public class LoginData
{
    public string username;
    public string password;
}

SendData.cs

public void SendLogin()
    {
        StartCoroutine(Login());
    }

    private IEnumerator Login()
    {
        var email = loginEmail.text;
        var password = loginPassword.text;
        var loginData = new LoginData();
        loginData.username = loginEmail.text;
        loginData.password = loginPassword.text;
        var json = JsonUtility.ToJson(loginData);

        using UnityWebRequest webRequest = new UnityWebRequest(loginUrl, "POST");
        webRequest.SetRequestHeader("Content-Type", "application/json; charset=utf-8");
        byte[] rawJson = System.Text.Encoding.UTF8.GetBytes(json);
        webRequest.uploadHandler = new UploadHandlerRaw(rawJson);
        webRequest.downloadHandler = new DownloadHandlerBuffer();
        yield return webRequest.SendWebRequest();

        switch(webRequest.result)
        {
            case UnityWebRequest.Result.InProgress:
                Debug.Log("In Progress...");
                break;
            case UnityWebRequest.Result.Success:
                Debug.Log(webRequest.downloadHandler.text);
                break;
            case UnityWebRequest.Result.ConnectionError:
                Debug.Log("Connection Error...");
                break;
            case UnityWebRequest.Result.ProtocolError:
                Debug.Log("Protocol Error...");
                break;
            case UnityWebRequest.Result.DataProcessingError:
                Debug.Log("Data Processing Error...");
                break;
            default:
                Debug.Log("Default...");
                break;
        }

    }

Server output from Postman

req.body = { username: '[email protected]', password: 'test' }
req.body.username.length = 13

Server output from Unity

req.body = { username: '[email protected]​', password: 'test​' }
req.body.username.length = 14

Server Login Route

router.post('/login', async (req, res, next) => {
    let username = req.body.username;
    console.log('req.body = '   req.body);
    console.log('req.body.username.length = '   username.length);
    User.findOne({email: username})
    .then(async(user) => {
        if(!user) {
            console.log('not found');
            return res.status(401).send('Invalid Credentials.')
        }

        if (user.failedLoginAttempts >= allowedFailedLoginAttempts) {
            return res.status(401).send('Account Locked.')
        }

        const isValidPassword = await GSUtility.isValidPassword(req.body.password, user.password)

        if (isValidPassword) {
            console.log('good');
            const jwt = GSUtility.issueJWT(user);
            user.updateLogin();
            return res.status(200).send({ user: user, token: jwt.token, expires: jwt.expires })
        } else {
            user.increaseFailedLoginAttempts();
            console.log('bad info');
            return res.status(401).send('Invalid Credentials.')
        }
    })
});

CodePudding user response:

Given the code you provided and a very minimal Node server, I cannot reproduce the issue you described.

I recommend checking if the issue still occurs when you manually hardcode the username/password values in the login data. I suspect the input field is adding a weird extra no-length whitespace character (or something like that) or that your issue is not actually between the client and the server but the actual values you are encoding in the first place.

You should also check and confirm how your server is handling body parsing, though I would suspect it is set up correctly if it's true that the request works fine from Postman. In the below example, I use the body-parser package, which works well.

Output from server:

Example app listening on port 3000
username.length: 13
{ username: '[email protected]', password: 'pasword' }

Example node server:

const express = require('express')
const bodyParser = require('body-parser')

const app = express()
const port = 3000

const jsonParser = bodyParser.json()

app.use(jsonParser)

app.get('/', (req, res) => {
    res.send('Hello World!')
});

app.post('/login', (req, res) => {
    const { username, password } = req.body
    console.log(`username.length: ${username.length}`)
    console.log({
        username,
        password
    })
    res.send({ message: 'success' })
});

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
});

Unity Script:

using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

[Serializable]
public class LoginData
{
    public string username;
    public string password;
}

public class WebRequestTest : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine(SendRequest());
    }

    private IEnumerator SendRequest()
    {
        var loginUrl = "http://localhost:3000/login";
        var loginData = new LoginData();
        loginData.username = "[email protected]";
        loginData.password = "pasword";
        var json = JsonUtility.ToJson(loginData);

        using UnityWebRequest webRequest = new UnityWebRequest(loginUrl, "POST");
        webRequest.SetRequestHeader("Content-Type", "application/json; charset=utf-8");
        byte[] rawJson = System.Text.Encoding.UTF8.GetBytes(json);
        webRequest.uploadHandler = new UploadHandlerRaw(rawJson);
        webRequest.downloadHandler = new DownloadHandlerBuffer();
        yield return webRequest.SendWebRequest();

        switch(webRequest.result)
        {
            case UnityWebRequest.Result.InProgress:
                Debug.Log("In Progress...");
                break;
            case UnityWebRequest.Result.Success:
                Debug.Log(webRequest.downloadHandler.text);
                break;
            case UnityWebRequest.Result.ConnectionError:
                Debug.Log("Connection Error...");
                break;
            case UnityWebRequest.Result.ProtocolError:
                Debug.Log("Protocol Error...");
                break;
            case UnityWebRequest.Result.DataProcessingError:
                Debug.Log("Data Processing Error...");
                break;
            default:
                Debug.Log("Default...");
                break;
        }
    }
}
  • Related