Получение двух объектов в req.body - PullRequest
2 голосов
/ 14 октября 2019

Я получаю POST-запрос от приложения Unity в формате x-form на мой веб-сервер NodeJ.

Я использую app.use(bodyParser.urlencoded({ extended: true})) для анализа содержимого. Но req.body возвращает два объекта, проблема в том, что я не могу получить доступ к свойству отдельного свойства, поскольку они не обернуты ни в массив, ни в объект.

Вкл. console.log(req.body)

Я получаюследующий результат

{ sessionId: '5ujgp6vwk1pivth4', gameId: '1', level: '0', score: '0' }            

{ sessionId: '5ujgp6vwk1pivth4', gameId: '2', level: '0', score: '0' }

Я хочу знать, какой это тип данных и как я смогу получить доступ к определенному свойству, предположим, что если я сделаю console.log(req.body.sessionId), я получу

5ujgp6vwk1pivth4

5ujgp6vwk1pivth4

Даже если я пытаюсь вставить его в массив, я все равно получаю тот же результат.

Я пытаюсь извлечь эти объекты в массив, чтобы мне было легче получить к ним доступ.

Сценарий для маршрутов Express:

const express = require('express')
const path = require('path')
const hbs = require('hbs')
const bodyParser = require('body-parser')
const viewsRouter = require('./routers/views')
const apiRouter = require('./routers/api')
const cookieParser = require('cookie-parser')
require ('./db/mongoose')

const app = express()
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true}))
app.use(cookieParser())
const publicDirectoryPath = path.join(__dirname,'../public')
app.use(express.static(publicDirectoryPath))
const viewsPath = path.join(__dirname,'../templates/views')
const partialsPath = path.join(__dirname,'../templates/partials')

hbs.registerPartials(partialsPath)
hbs.registerHelper('ifCond', function(v1, v2, options) {
if(v1 === v2) {
return options.fn(this);
}
return options.inverse(this);
});
hbs.registerHelper("math", function(lvalue, operator, rvalue, options) {
lvalue = parseFloat(lvalue);
rvalue = parseFloat(rvalue);

return {
  "+": lvalue + rvalue,
  "-": lvalue - rvalue,
  "*": lvalue * rvalue,
  "/": lvalue / rvalue,
  "%": lvalue % rvalue
  }[operator];
  });
app.use(viewsRouter)
app.use(apiRouter)
// For any of the un-handled routes
app.get('*',(req,res)=>{
res.render('error')
})

//Setting up the CORS functionality in Express for Making AJAX calls
app.use(function(req, res, next) {

res.header("Access-Control-Allow-Origin", "*");

res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");

next();

});

app.set('views',viewsPath)
app.set('view engine','hbs')


app.listen(80,()=>{
console.log('Server Started on Port 80')
})

Маршрут, отвечающий за конкретный POST,

apiRouter.post('/api/updateScore/',async(req,res)=>{ 
console.log(req.body)
})

Клиентский скрипт:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using UnityEngine.SceneManagement;
using System.Text;

public class ScoreSender : MonoBehaviour {

public Authentication authentication;
public  static readonly string scoreUrl = "https://eyenet.pythonanywhere.com/scores/";
public static ScoreSender instance;
public string Address = "127.0.0.1:8000";
// Use this for initialization
void Start () {
    instance = this;
}

// Update is called once per frame
void Update () {

}

public void sendScore(int gameId, int level)
{

}

public void sendScore(string gameId, int level, int score)
{
    string loginURL = Address+ "/api/updateScore/";

    WWWForm form = new WWWForm();
    form.AddField( "sessionId", authentication.session );
    Dictionary<string, string> headers = form.headers;
    byte[] rawData = form.data;

    WWW www = new WWW(loginURL, rawData, headers);

}
    // StartCoroutine(WaitForRequest(www));



public void saveScore(string gameId, int nextlevel, int score)
{

    // get session id
    string sessionCode = authentication.session;

    // get score array
    int noOfGames = PlayerPrefs.GetInt("totalGames",0);

    // get or create score, level, nextlevel arrays
    int gid = int.Parse(gameId);


    //
    int[] scoreArray = PlayerPrefsX.GetIntArray(sessionCode+"scores",0,noOfGames+1);
    int[] nextLevelsArray = PlayerPrefsX.GetIntArray(sessionCode+"nextLevels",0,noOfGames+1);

    nextLevelsArray[gid] = nextlevel;
    scoreArray[gid] = score;

    PlayerPrefsX.SetIntArray(sessionCode+"scores",scoreArray);
    PlayerPrefsX.SetIntArray(sessionCode+"nextLevels",nextLevelsArray);

    PlayerPrefsX.SetIntArray("gameLevels",nextLevelsArray);
    Debug.Log("saved score and nextLevels offline");
}

//for sending score to the cloud


public void uploadScore()
{
    //testing
    //StartCoroutine(scoreSend(authentication.session,"1",45,34));
    syncScore(authentication.session);

}


//for online sessions only
void syncScore(string sessionId)
{
    Debug.Log("We are syncing the score for this session");

    int noOfGames = PlayerPrefs.GetInt("totalGames",0);
    int[] currentGamePlays = PlayerPrefsX.GetIntArray(sessionId+"currentGamePlays",0,noOfGames);
    int[] scoreArray = PlayerPrefsX.GetIntArray(sessionId+"scores",0,noOfGames+1);
    int[] nextLevelsArray = PlayerPrefsX.GetIntArray(sessionId+"nextLevels",0,noOfGames+1);


    for(int i=0;i<noOfGames+1;i++)
    {
        if(currentGamePlays[i]==1)  //if the game is played in this session
        {
            StartCoroutine( scoreSend(sessionId,""+i,nextLevelsArray[i],scoreArray[i]));
            Debug.Log("score:"+scoreArray[i]);
            Debug.Log("level:"+nextLevelsArray[i]);
        }
    }
}


public int noOfScores=0;

public void syncOfflineScore(int num,string actualId)
{
    string sessionId = "offlineSession"+num;

    int noOfGames = PlayerPrefs.GetInt("totalGames",0);
    int[] currentGamePlays = PlayerPrefsX.GetIntArray(sessionId+"currentGamePlays",0,noOfGames+1);
    int[] scoreArray = PlayerPrefsX.GetIntArray(sessionId+"scores",0,noOfGames+1);
    int[] nextLevelsArray = PlayerPrefsX.GetIntArray(sessionId+"nextLevels",0,noOfGames+1);


    for(int i=0;i<noOfGames+1;i++)
    {
        if(currentGamePlays[i]==1)  //if the game is played in this session
        {
            noOfScores++;
        }
    }


    for(int i=0;i<noOfGames+1;i++)
    {
        if(currentGamePlays[i]==1)  //if the game is played in this session
        {
            StartCoroutine( offlineScoreSend(actualId,""+i,nextLevelsArray[i],scoreArray[i]));
            Debug.Log("score:"+scoreArray[i]);
            Debug.Log("level:"+nextLevelsArray[i]);
        }
    }


}







//working fine
IEnumerator scoreSend(string sessionId,string gameId,int nextlevel, int score)
{
    string scoreUrl = authentication.Address+ "/api/updateScore/";

    WWWForm form = new WWWForm();

    form.AddField( "sessionId", sessionId );
    form.AddField( "gameId", gameId );
    form.AddField( "level", nextlevel);
    form.AddField( "score", score);

    Dictionary<string, string> headers = form.headers;
    //Dictionary<string, string> headers = new Dictionary<string, string>();
    //headers.Add("Content-Type", "application/json");
    byte[] rawData = form.data;

    WWW www = new WWW(scoreUrl, rawData, headers);
    WWW data =www;

    yield return data;
    if(data.error!=null)
    {
        Debug.Log (data.error); 

        if(data.error == "Cannot connect to destination host")
        {

        }

    }
    else
    {
        Debug.Log(data.text);
        ServerResponse res = JsonUtility.FromJson<ServerResponse>(data.text);
        if(res.status==0)
        {
            Debug.Log("Updated score");

        }   
        else
        {
            Debug.Log("Got an error");
        }
    }
}


//test it
IEnumerator offlineScoreSend(string sessionId,string gameId,int nextlevel, int score)
{
    string scoreUrl = authentication.Address+ "/api/updateScore/";

    WWWForm form = new WWWForm();

    form.AddField( "sessionId", sessionId );
    form.AddField( "gameId", gameId );
    form.AddField( "level", nextlevel);
    form.AddField( "score", score);

    Dictionary<string, string> headers = form.headers;
    byte[] rawData = form.data;

    WWW www = new WWW(scoreUrl, rawData, headers);
    WWW data =www;

    yield return data;
    if(data.error!=null)
    {
        Debug.Log (data.error); 

        if(data.error == "Cannot connect to destination host")
        {

        }

    }
    else
    {
        Debug.Log(data.text);
        ServerResponse res = JsonUtility.FromJson<ServerResponse>(data.text);
        if(res.status==0)
        {
            Debug.Log("Updated score");
            noOfScores--;
            if(noOfScores==0)
            {
                authentication.syncOfflineSessionsDataComplete();
            }
        }   
        else
        {
            Debug.Log("Got an error");
        }
    }
}





}

1 Ответ

2 голосов
/ 14 октября 2019

К сожалению, то, что происходит, отличается от того, что, как вы думаете, происходит, и здесь недостаточно информации, чтобы понять, что на самом деле происходит. Вы говорите, что req.body возвращает два объекта, но они не заключены в массив или другой объект, что принципиально невозможно.

Учитывая доступную информацию, я думаю, что bodyParser работает точнокак и должно быть, но любое клиентское приложение, которое вы используете для отправки запросов, отправляет два запроса, когда вы думаете, что оно отправляет только один, поэтому, когда вы регистрируете его, вы видите два объекта и предполагаете, что они пришли из одного вызова console.log, которыйпохоже, дело не в этом.

Чтобы подтвердить это, я, вероятно, вставил бы что-то подобное в конец файла, а затем использовал бы это для входа вместо непосредственного использования console.log. Это продемонстрирует, что это две разные записи журнала, поступающие из двух разных вызовов маршрута.

let counter = 0;
function logWithCounter( ...msg ) {
  console.log( counter++, ...msg );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...