【问题标题】:Generic/Unknown HTTP Error with response code 0 using UnityWebRequest使用 UnityWebRequest 的响应代码为 0 的通用/未知 HTTP 错误
【发布时间】:2018-10-14 00:47:57
【问题描述】:

我尝试使用一些服务器的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
    }

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

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

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

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

【问题讨论】:

  • 也许可以尝试一些不同的方法,比如this one

标签: http unity3d unity-webgl


【解决方案1】:

潜在解决方案 1

Unity documentation 开始,将 UnityWebRequest 与 WebGL 结合使用:

WebGL 支持 WWW 和 UnityWebRequest 类。它们是使用 JavaScript 中的 XMLHttpRequest 类实现的,使用浏览器处理 WWW 请求。这对访问跨域资源施加了一些安全限制。基本上,对不同于托管 WebGL 内容的服务器的任何 WWW 请求都需要由您尝试访问的服务器授权。要在 WebGL 中访问跨域 WWW 资源,您尝试访问的服务器需要使用 CORS 进行授权。

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

如果这是您的问题,那么如果没有更多信息,我很难提出解决方案。从您的帖子中,听起来您可能对编码(或至少对与 HTTP 相关的编码)比较陌生,而我能找到的解决您的问题的最佳解决方案涉及一些相对复杂的方法,例如 using JavaScript 而不是 @987654324 @。

潜在解决方案 2

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

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

【讨论】:

  • 潜在的解决方案 1 正是我的情况,稍后我通过查看浏览器的控制台和谷歌搜索错误发现了它。显然,我需要更仔细地阅读文档。因此,如果您(或您的同事)是服务器的所有者并且可以更改它发送的 HTTP 响应,则需要添加特殊的 HTTP 标头,这些标头在此答案提到的 Unity 文档中编写。希望这会帮助任何人,他们会得到同样的错误。谢谢。
【解决方案2】:

首先要指出的是,UnityWebRequest实际上是在返回响应

request.downloadHandler.text

虽然在

中只返回一般错误信息

request.error


现在,如果您的情况与我的情况类似,并且您升级 Unity 只是为了让您的所有网络代码中断,那么您可能会看到与 Content-Length 相关的错误

这是因为 WWW 和 UnityWebRequest 类现在都默认启用了 chunkedTransfer。这似乎搞砸了内容长度的发送方式并导致错误。

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

myUnityWebRequest.chunkedTransfer = false;

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

【讨论】:

    【解决方案3】:

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

    启用 CORS:

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

    在 Postman 中测试:

    需要在 Postman 中测试您的 API。如果您的应用程序不支持 CORS,它仍然可以在 Postman 中运行。所以在 postman 中工作并不能保证它会在 Unity 中运行。 下一个要考虑的重要事项是您在邮递员中使用的标头。

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

    因为你还需要在统一的 www 标头中传递它。

    接下来需要观察的是你在体内传递了什么以及你是如何传递的。通常我们在 Postman 中将其作为 JSON(application/json) 发送。

    喜欢:

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

    现在,如果您启用 CORS 的 API 在 Postman 中运行良好,那么放松一下,它也可以统一运行。

    统一部分:

    首先我必须创建一个将转换为 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;
        }
    
    }
    

    接下来您必须将对象转换为 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转成byte,并用header做post。

    //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 要求发布或发送数据。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-13
      • 1970-01-01
      • 2019-01-29
      • 2018-11-29
      • 1970-01-01
      相关资源
      最近更新 更多