it-swarm.com.de

Generischer/unbekannter HTTP-Fehler mit Antwortcode unter Verwendung von UnityWebRequest

Ich habe versucht, die API-Funktionen einiger Server zu verwenden, und bin plötzlich auf diesen Fehler gestoßen. Ich werde es nach dem Codebeispiel erklären:

public IEnumerator Post(Dictionary<string, string> data)
    {
        var request = UnityWebRequest.Post(Url, data);
        request.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded");

        yield return request.Send();

        if (request.isError)
           UpdateNetworkLog("Network error has occured: " + request.error);
        else
            // Some code after success
    }

Wie Sie sehen können, habe ich es hauptsächlich aus dem Unity-Handbuch entnommen und dabei POST Anforderungen berücksichtigt hier . Es gibt jedoch ein Problem: Die Anforderung wurde nie ordnungsgemäß beendet. Es ist immer ein Fehler aufgetreten (der mit der Funktion UpdateNetworkLog angezeigt wird): "Allgemeiner/unbekannter HTTP-Fehler", während der Antwortcode der Anforderung 0 lautet. Außerdem habe ich versucht, eine ältere Version zu verwenden Methode aus diesem Handbuch und WWW-Klasse erhalten das gleiche Ergebnis.

Ich denke, das Problem liegt darin, wie Unity die Antwort erhält: Ich habe Pakete über Wireshark überprüft. Sowohl meine POST -Anforderung als auch die Antwort des Servers sind in Ordnung, keine Fehler oder Irrtümer.

Ein weiteres wichtiges Problem ist, dass ich WebGL verwende und im Editor alles in Ordnung ist. Das Programm erhält die richtige Antwort und funktioniert ordnungsgemäß. Der Fehler wird erst angezeigt, nachdem ich das Spiel im Browser erstellt und ausgeführt habe (getestet in Chrome und Safari). Versuchen Sie es auch, indem Sie nicht den Unity WebGL-Player, sondern XAMPP: verwenden.

Vielen Dank für all die zukünftigen Antworten, da Google nichts darüber weiß.

3
KotovP

Mögliche Lösung 1

Aus der Unity-Dokumentation über die Verwendung von UnityWebRequest mit WebGL:

Die Klassen WWW und UnityWebRequest werden in WebGL unterstützt. Sie werden mithilfe der XMLHttpRequest-Klasse in JavaScript implementiert, wobei der Browser zum Verarbeiten von WWW-Anforderungen verwendet wird. Dies bedingt einige Sicherheitsbeschränkungen für den Zugriff auf domänenübergreifende Ressourcen. Grundsätzlich muss jede WWW-Anforderung an einen Server, die sich von dem Server unterscheidet, auf dem der WebGL-Inhalt gehostet wird, von dem Server autorisiert werden, auf den Sie zugreifen möchten. Für den Zugriff auf domänenübergreifende WWW-Ressourcen in WebGL muss der Server, auf den Sie zugreifen möchten, dies mit CORS autorisieren.

Ich vermute, dass auf diesem Server, auf den Sie zugreifen möchten, CORS nicht richtig eingerichtet oder konfiguriert ist. Wenn Ihr Code in einem Browser ausgeführt wird, verarbeitet der Browser selbst die Anforderung und unterwirft Ihren Code folglich den Sicherheitsbeschränkungen dieses Browsers. Ihr Programm und der Server befinden sich nicht in derselben Domäne, und das gefällt dem Browser nicht.

Wenn dies Ihr Problem ist, ist es für mich ohne weitere Informationen schwierig, eine Lösung vorzuschlagen. In Ihrem Beitrag klingt es so, als wären Sie relativ neu in der Codierung (oder zumindest in Bezug auf HTTP), und die besten Lösungen für Ihr Problem beinhalten einige relativ komplexe Methoden, z. B. Verwenden von JavaScript von UnityWebRequest.

Mögliche Lösung 2

Das eigentliche Problem könnte natürlich auch an Ihrem Umgebungscode liegen oder an dem Server, auf den Sie zugreifen möchten. Wie lautet Ihr Code für die Funktion, die Post() aufruft? Möglicherweise liegt ein Problem mit der Reihenfolge der Ereignisse vor, das nur angezeigt wird, wenn der Code in einem Browser ausgeführt wird (wobei JavaScript die Anforderung POST verarbeitet).

Wenn der Server, auf den Sie zugreifen möchten, über Dokumentation zu seiner API verfügt, wird Ihr Problem möglicherweise irgendwo darin behoben.

4
Allison Meek

Als Erstes muss darauf hingewiesen werden, dass UnityWebRequest die Antwort tatsächlich in zurückgibt

request.downloadHandler.text

Während nur die allgemeinen Fehlerinformationen in zurückgegeben werden

request.error


Wenn Ihr Fall nun wie meiner ist und Sie Unity aktualisiert haben, um nur Ihren gesamten Netzwerkcode zu brechen, hängt der Fehler, den Sie wahrscheinlich sehen, mit Content-Length zusammen.

Dies liegt daran, dass sowohl für die WWW- als auch für die UnityWebRequest-Klasse chunkedTransfer standardmäßig aktiviert ist . Dies scheint zu vermasseln, wie lange der Inhalt gesendet wird, und verursacht den Fehler.

Während chunkedTransfer derzeit für UnityWebRequest deaktiviert werden kann, kann es zum Zeitpunkt des Schreibens nicht für die WWW-Klasse deaktiviert werden. Für mich bedeutete dies, meinen gesamten alten Netzwerkcode neu zu schreiben, um stattdessen UnityWebRequest zu verwenden und festzulegen

myUnityWebRequest.chunkedTransfer = false;

Hinweis: UnityWebRequest unterstützt derzeit keine POSTs ohne Daten. Sie müssen dafür noch die WWW-Klasse verwenden.

5
Maxx

Dieses Problem ist sehr verbreitet. Wenn Sie mit Rest API gearbeitet haben, sind die Dinge ziemlich einfach zu verstehen.

CORS aktivieren:

Ich habe eine Rest-API mit Python Flask erstellt und sie wurde in Heroku gehostet. Der Vorteil von Heroku war, dass es standardmäßig CORS unterstützt und Sie es nicht einrichten müssen. Heutzutage hat der maximale Server, auf dem Sie Ihre App hosten, insbesondere Python, die gleiche Funktion. Wenn Sie also ein CORS-Problem haben, müssen Sie zuerst CROS aktivieren. Dies ist obligatorisch.

Test im Postboten:

Es ist erforderlich, um Ihre API in Postman zu testen. Wenn Ihre App CORS immer noch nicht unterstützt, funktioniert sie in Postman. Die Arbeit mit dem Postboten stellt also nicht sicher, dass er in Unity ausgeführt wird. Als nächstes sollten Sie die Header berücksichtigen, die Sie im Postboten verwenden.

Wie: {"Schlüssel": "Inhaltstyp", "Wert": "application/json" }

weil Sie es auch in Einheit WWW-Header übergeben müssen.

Als nächstes müssen Sie beobachten, was Sie im Körper passieren und wie Sie es passieren. Normalerweise senden wir es als JSON (application/json) in Postman.

Mögen:

`{
    "username":"Mukesh",
    "password":"[email protected]",
    "email_id":"[email protected]",
    "us_dollar":"2000000000",
    "device_id":"123456789"

}`

Wenn Ihre CORS-fähige API in Postman einwandfrei funktioniert, können Sie sich einfach entspannen. Dies funktioniert auch in Einheit.

Einheitsteil:

Zuerst muss ich eine Klasse erstellen, die in Json konvertiert wird.

[Serializable]
public class UserRegistration
{
    //CAUTION:
    //NOTE:
    //DO NOT ALTER THE NAME OF PARAMETERS .
    //THE JSON key WILL FAIL THEN .Properties will be the key of JSON .
    /// <summary>
    /// User name .
    /// </summary>
    public  string username;
    /// <summary>
    /// Password .
    /// </summary>
    public string password;
    /// <summary>
    /// Emil id.
    /// </summary>
    public string email_id;
    /// <summary>
    /// JoeGames Doller .
    /// </summary>
    public string us_dollar;
    /// <summary>
    /// Device id .
    /// </summary>
    public  string device_id;

    /// <summary>
    /// Constructor .
    /// </summary>
    /// <param name="username"></param>
    /// <param name="password"></param>
    /// <param name="email_id"></param>
    /// <param name="us_dollar"></param>
    /// <param name="device_id"></param>
    public UserRegistration(string username, string password, string email_id, string us_dollar, string device_id)
    {
        this.username = username;
        this.password = password;
        this.email_id = email_id;
        this.us_dollar = us_dollar;
        this.device_id = device_id;
    }

}

Als nächstes müssen Sie das Objekt in json konvertieren.

//var create json.
    var userregistration = new UserRegistration(
        username: username,
        password: password,
        email_id: emailid,
        us_dollar: joeGamesDollar.ToString(),
        device_id: deviceid);
    //convert to json.
    var json = JsonUtility.ToJson(userregistration);
    //debug.
    Debug.Log("Print json"+json);
    //update json.
    json = json.Replace("'", "\"");

Als nächstes konvertieren Sie json in das Byte und machen den Beitrag mit dem Header.

//Encode the JSON string into a bytes
    var postData = System.Text.Encoding.UTF8.GetBytes(json);
    //create headers.
    //Add keys an values .
    var headers = new Dictionary<string, string> {{"Content-Type", "application/json"}};
    //Now call a new WWW request
    var www = new WWW(url,postData,headers);
    //Yield return www .
    yield return www;

    Debug.Log("Error" + www.error.ToString());
    Debug.Log("Data" + www.text);
    Debug.Log(www.responseHeaders+"Done"+www.isDone);
    //dispose.
    www.Dispose();

Vergessen Sie nicht, es in einen Enumerator zu schreiben. Wenn du etwas verwendest

mögen:

IEnumerator Upload()
    {
        WWWForm form = new WWWForm();
        form.AddField("username", "Mukesh");
        form.AddField("password", "[email protected]");
        form.AddField("email_id", "[email protected]");
        form.AddField("us_dollar", "2000000");
        form.AddField("device_id", device_id);


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

            if (www.isNetworkError || www.isHttpError)
            {
                Debug.Log(www.error);
            }
            else
            {
                Debug.Log("Form upload complete!");
            }
        }
    } 

Sie erhalten einen generischen/unbekannten Fehler, weil Unity Web Request unter diesen Umständen die erforderlichen Daten nicht als API bereitstellen oder senden kann.

HINWEIS: Irgendwann wird 400 Bad Request auch als unbekannter generischer/unbekannter HTTP-Fehler in Unity angezeigt. Vergessen Sie also nicht, den Code im Backend zu überprüfen, um sicherzustellen, dass Ihre API keine Ausnahme erhält.

1
Reezoo Bose