Malformed HTTP post using WWWForm
我正在使用UnityHTTP(https://github.com/andyburke/UnityHTTP)来调用REST API(KiiCloud http://www.kii.com),它的效果很好,但是我想摆脱第3方库如果可能的话,并使用Unity的WWW和WWWForm实现相同的目的。
这是使用UnityHTTP的代码,可以正常工作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | public static void RunServerExtension (string appId, string appKey, string endpoint, string kii_access_token, string msg) { Hashtable data = new Hashtable(); // Add json fields with values here (use as dictionary) data.Add("message", msg); // When you pass a Hashtable as the third argument, we assume you want it send as JSON-encoded // data. We'll encode it to JSON for you and set the Content-Type header to application/json HTTP.Request myRequest = new HTTP.Request("post","https://api.kii.com/api/apps/" + appId +"/server-code/versions/current/" + endpoint, data); myRequest.AddHeader("x-kii-appid", appId); myRequest.AddHeader("x-kii-appkey", appKey); if(kii_access_token != null) theRequest.AddHeader("Authorization","Bearer" + kii_access_token); myRequest.Send( ( request ) => { // we provide Object and Array convenience methods that attempt to parse the response as JSON // if the response cannot be parsed, we will return null // note that if you want to send json that isn't either an object ({...}) or an array ([...]) // that you should use JSON.JsonDecode directly on the response.Text, Object and Array are // only provided for convenience Hashtable result = request.response.Object; if ( result == null ) { Debug.LogWarning("Could not parse JSON response!" ); return; } Debug.Log ("Got response"); Debug.Log(request.response.Text); }); } |
所以上面的工作很好,但是当我以这种方式切换到WWWForm时:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | public static WWW RunServerExtension (string appId, string appKey, string endpoint, string kii_access_token, string msg) { WWWForm form = new WWWForm(); Hashtable headers = form.headers; headers["Content-Type"] ="application/json"; headers["x-kii-appid"] = appId; headers["x-kii-appkey"] = appKey; if(kii_access_token != null) headers["Authorization"] ="Bearer" + kii_access_token; form.AddField("message", msg); return new WWW("https://api.kii.com/api/apps/" + appId +"/server-code/versions/current/" + endpoint, form.data, headers); } private IEnumerator WaitForRequest(WWW www) { yield return www; // check for errors if (www.error == null) { Debug.Log("WWW Ok!:" + www.text); } else { Debug.Log("WWW Error:"+ www.error); } } |
我在服务器端收到错误请求(意味着请求格式错误,而不是服务器期望的内容)。请注意,必须将标头作为参数传递,否则服务器会抱怨缺少标头。
我怀疑这可能与服务器需要JSON数据有关,因此我使用UnityHTTP JSON类(您可以仅使用该隔离的类进行JSON编码/解码)将消息转换为JSON https://github.com/andyburke/ UnityHTTP / blob / master / external / JSON.cs,因此此方法将{" message":" This is echoed !!"}作为数据传递:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public static WWW RunServerExtension (string appId, string appKey, string endpoint, string kii_access_token, string msg) { WWWForm form = new WWWForm(); Hashtable headers = form.headers; headers["Content-Type"] ="application/json"; headers["x-kii-appid"] = appId; headers["x-kii-appkey"] = appKey; if(kii_access_token != null) headers["Authorization"] ="Bearer" + kii_access_token; Hashtable data = new Hashtable(); data["message"] = msg; byte[] bytes = GetBytes(JSON.JsonEncode(data)); return new WWW("https://api.kii.com/api/apps/" + appId +"/server-code/versions/current/" + endpoint, bytes, headers); } static byte[] GetBytes(string str) { byte[] bytes = new byte[str.Length * sizeof(char)]; System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length); return bytes; } |
但是仍然有相同的错误请求。您知道为什么这可能会失败吗?为什么UnityHTTP可以工作?
正如我在评论中提到的:C#将所有字符串转换为UTF-16。 如果您的网络服务器期望使用不同的编码,则仅逐字传递字节将不会产生良好的结果。
JSON通常以UTF-8编码,但是最好是API明确指定其输入/输出编码。
今天,我花了更多时间。 如果检查UnityHTTP的源代码,则可以看到其Hashtable构造函数以UTF-8编码JSON:
1 | this.bytes = Encoding.UTF8.GetBytes( JSON.JsonEncode( data ) ); |
您的代码不会更改字符串的编码,这意味着您发送的字节错误。