Generic/Unknown 使用 UnityWebRequest 时出现响应代码为 0 的 HTTP 错误

Generic/Unknown HTTP Error with response code 0 using UnityWebRequest

我正在尝试使用一些服务器的 API 功能,突然遇到这个错误。我会在代码示例之后解释它:

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
    }

如您所见,考虑到 POST 请求 here,我主要从 Unity 手册中获取它。但是,有一个问题 - 请求从未正确完成,它总是有错误(使用 UpdateNetworkLog 函数显示):"Generic/unknown HTTP error",而请求的响应代码为 0。另外,我尝试使用来自本手册和 WWW class 得到相同的结果。

我认为,问题在于 Unity 如何获得响应:我已经通过 Wireshark 检查数据包,我的 POST 请求和服务器的响应都非常好,没有错误。

另一个重要的问题是我正在使用WebGL,在编辑器中一切正常,程序得到正确的响应并正常工作;只有在我在浏览器中构建和 运行 游戏后才会出现错误(在 Chrome 和 Safari 中测试)。此外,尝试不使用 Unity WebGL Player 启动它,但 XAMPP:相同。

感谢所有未来的回复,因为 Google 对此一无所知。

可能的解决方案 1

来自 Unity documentation 关于将 UnityWebRequest 与 WebGL 结合使用的文章:

The WWW and UnityWebRequest classes are supported in WebGL. They are implemented using the XMLHttpRequest class in JavaScript, using the browser to handle WWW requests. This imposes some security restrictions on accessing cross-domain resources. Basically any WWW request to a server which is different from the server hosting the WebGL content needs to be authorized by the server you are trying to access. To access cross-domain WWW resources in WebGL, the server you are trying to access needs to authorize this using CORS.

我最好的猜测是您尝试访问的服务器没有正确设置或配置 CORS。当您的代码在浏览器中 运行ning 时,浏览器本身正在处理请求并因此使您的代码受制于该浏览器的安全限制。您的程序和服务器不在同一个域中,浏览器不喜欢这样。

如果这是您的问题,那么在没有更多信息的情况下,我很难提出解决方案。从你的 post 来看,你可能对编码(或至少对 HTTP 相关的编码)比较陌生,我能找到的解决你问题的最佳方法涉及一些相对复杂的方法,例如 using JavaScript 而不是 UnityWebRequest.

可能的解决方案 2

当然,实际问题甚至可能出在您周围的代码上,或者出在您尝试访问的服务器上。调用 Post() 的函数的代码是什么?仅当浏览器中的代码为 运行 时(其中 JavaScript 正在处理 POST 请求),事件顺序可能存在一些问题。

附带说明一下,如果您尝试访问的服务器有其 API 的文档,您的问题可能会在其中某处得到解决。

首先要指出的是 UnityWebRequest 实际上 returns

中的响应

request.downloadHandler.text

而在

中只返回一般错误信息

request.error


现在,如果您的情况和我一样,并且您升级 Unity 只是为了破坏所有网络代码,您可能会看到的错误与 Content-Length

这是因为对于 WWW 和 UnityWebRequest class 现在默认 chunkedTransfer 打开 。这似乎搞砸了内容长度的发送方式并导致错误。

虽然当前可以为 UnityWebRequest 禁用 chunkedTransfer,但在撰写本文时无法为 WWW class 禁用它。对我来说,这意味着重写我所有的旧网络代码以改用 UnityWebRequest 并设置

myUnityWebRequest.chunkedTransfer = false;

注意:UnityWebRequest目前不支持没有数据的POST。您仍然需要为此使用 WWW class。

这个问题很常见。如果您使用过 Rest API 那么事情就很容易理解了。

启用 CORS:

我使用 python flask 创建了一个 rest API,它托管在 Heroku 中。 Heroku 的优点是它默认支持 CORS,你不需要设置它。如今,您托管应用程序的最大服务器,尤其是 python 具有相同的功能。所以那些有 CORS 相关问题的人必须首先启用 CROS,这是强制性的。

在 Postman 中测试:

需要在 Postman 中测试您的 API。如果您的应用程序不支持 CORS,它仍然可以在 Postman 中运行。因此,在 postman 中工作并不能确保它会在 Unity 中 运行。 下一个要考虑的重要事项是您在 postman.

中使用的 Headers

喜欢:{"Key":"Content-Type","value":"application/json"}

因为你还需要在unity中传递它 www header.

接下来需要观察的是您在 body 中传递的内容以及传递方式。通常我们在 Postman 中将其发送为 JSON(application/json)。

喜欢:

`{
    "username":"Mukesh",
    "password":"admin@1234",
    "email_id":"mukeshh@gmail.com",
    "us_dollar":"2000000000",
    "device_id":"123456789"

}`

现在,如果您的 CORS 启用 API 在 Postman 中工作正常,那么只需放松它也可以统一工作。

统一部分:

首先,我必须创建一个 class,它将转换为 Json。

[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;
    }

}

接下来您必须将 object 转换为 json。

//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("'", "\"");

接下来,将json转换成字节,使post变成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();

别忘了把它写在枚举器中。 如果你使用某些东西

喜欢:

IEnumerator Upload()
    {
        WWWForm form = new WWWForm();
        form.AddField("username", "Mukesh");
        form.AddField("password", "admin@1234");
        form.AddField("email_id", "mikesh@gmail.com");
        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!");
            }
        }
    } 

您将收到一般/未知错误,因为在这种情况下,Unity Web 请求无法按照您的 API 要求进行 post 或发送数据。

注意: 有时 400 Bad request 也作为一个未知的 Generic/Unknown 统一 HTTP 错误。所以不要忘记检查后端代码以确保您的 API 没有出现任何异常。