Unity调用本地GraphQL登录Mutation时返回400 Bad Request错误求助
问题:Unity中UnityWebRequest调用GraphQL登录接口返回400错误及JSON解析失败
我用Unity的UnityWebRequest向本地GraphQL服务器发起登录请求,这个登录Mutation在Apollo Client和Postman里都能正常执行,但在Unity里遇到两个问题:
- HTTP/1.1 400 Bad Request网络错误
- 服务器返回JSON解析语法错误(Unexpected token %)
已经试过调整查询语句的写法(比如query/mutation大小写),但问题还是存在。
报错信息1
Network error: HTTP/1.1 400 Bad Request UnityEngine.Debug:LogError (object) GraphApi/<LoginMutation>d__3:MoveNext () (at Assets/GraphApi.cs:61) UnityEngine.SetupCoroutine:InvokeMoveNext (System.Collections.IEnumerator,intptr)
报错信息2
Response body: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Error</title> </head> <body> <pre>SyntaxError: Unexpected token % in JSON at position 0<br> at JSON.parse (<anonymous>)<br> at createStrictSyntaxError (C:\snapshot\agent\_work\43\s\src\PLF\Exe\Services\GraphQL\NodeJsServer\node_modules\body-parser\lib\types\json.js:160:10)<br> at parse (C:\snapshot\agent\_work\43\s\src\PLF\Exe\Services\GraphQL\NodeJsServer\node_modules\body-parser\lib\types\json.js:83:15)<br> at C:\snapshot\agent\_work\43\s\src\PLF\Exe\Services\GraphQL\NodeJsServer\node_modules\body-parser\lib\read.js:128:18)<br> at AsyncResource.runInAsyncScope (node:async_hooks:203:9)<br> at invokeCallback (C:\snapshot\agent\_work\43\s\src\PLF\Exe\Services\GraphQL\NodeJsServer\node_modules\raw-body\index.js:231:16)<br> at done (C:\snapshot\agent\_work\43\s\src\PLF\Exe\Services\GraphQL\NodeJsServer\node_modules\raw-body\index.js:220:7)<br> at IncomingMessage.onEnd (C:\snapshot\agent\_work\43\s\src\PLF\Exe\Services\GraphQL\NodeJsServer\node_modules\raw-body\index.js:280:7)<br> at IncomingMessage.emit (node:events:525:35)<br> at endReadableNT (node:internal/streams/readable:1358:12)</pre> </body> </html> UnityEngine.Debug:LogError (object) GraphApi/<LoginMutation>d__3:MoveNext () (at Assets/GraphApi.cs:64) UnityEngine.SetupCoroutine:InvokeMoveNext (System.Collections.IEnumerator,intptr)
相关C#代码
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Networking; using TMPro; using System.Net.Http; using System; using System.Threading.Tasks; using static Unity.IO.LowLevel.Unsafe.AsyncReadManagerMetrics; using static UnityEditor.Progress; using static UnityEditor.ShaderData; using System.Drawing; using Unity.VisualScripting; public class GraphApi : MonoBehaviour { public TextMeshProUGUI text; public class BypassCertificate : CertificateHandler { protected override bool ValidateCertificate(byte[] certificateData) { // 跳过证书验证 return true; } } void Start() { StartCoroutine(LoginMutation()); } IEnumerator LoginMutation() { Debug.Log(@"""" == "\""); string graphqlEndpoint = "https://notebook65/graphql/"; string mutation = @"mutation Login { login(username: ""admin"", password: ""xxx"") { token error { code description } } } "; string jsonRequestBody = "{\"mutation\" : \"" + mutation + "\"}"; Debug.Log(jsonRequestBody); text.text = jsonRequestBody; using UnityWebRequest www = UnityWebRequest.Post(graphqlEndpoint, jsonRequestBody); //www.SetRequestHeader("Accept", "application/json"); www.SetRequestHeader("Content-Type", "application/json"); // 禁用SSL验证 www.certificateHandler = new BypassCertificate(); yield return www.SendWebRequest(); if (www.result != UnityWebRequest.Result.Success) { Debug.LogError("Network error: " + www.error); if (!string.IsNullOrEmpty(www.downloadHandler.text)) { Debug.LogError("Response body: " + www.downloadHandler.text); } } else { string responseBody = www.downloadHandler.text; Debug.Log("Response body: " + responseBody); text.text = responseBody; } } }
解决方案
问题核心是手动拼接JSON时未处理字符串中的特殊字符(换行、引号等),导致生成的JSON格式无效,服务器无法解析;同时UnityWebRequest.Post默认按表单提交处理,与application/json的请求头冲突。
修复步骤及代码示例
using System.Collections; using UnityEngine; using UnityEngine.Networking; using TMPro; public class GraphApi : MonoBehaviour { public TextMeshProUGUI text; public class BypassCertificate : CertificateHandler { protected override bool ValidateCertificate(byte[] certificateData) { // 跳过证书验证 return true; } } // 定义序列化类,用于生成合法JSON [System.Serializable] private class GraphQLRequest { public string mutation; } void Start() { StartCoroutine(LoginMutation()); } IEnumerator LoginMutation() { string graphqlEndpoint = "https://notebook65/graphql/"; string mutation = @"mutation Login { login(username: ""admin"", password: ""xxx"") { token error { code description } } } "; // 通过JsonUtility序列化生成合法JSON,自动处理特殊字符 GraphQLRequest request = new GraphQLRequest { mutation = mutation }; string jsonRequestBody = JsonUtility.ToJson(request); Debug.Log(jsonRequestBody); text.text = jsonRequestBody; // 手动构建POST请求,使用原始字节数组传递JSON using UnityWebRequest www = new UnityWebRequest(graphqlEndpoint, "POST"); byte[] bodyRaw = System.Text.Encoding.UTF8.GetBytes(jsonRequestBody); www.uploadHandler = new UploadHandlerRaw(bodyRaw); www.downloadHandler = new DownloadHandlerBuffer(); www.SetRequestHeader("Content-Type", "application/json"); www.SetRequestHeader("Accept", "application/json"); // 禁用SSL验证 www.certificateHandler = new BypassCertificate(); yield return www.SendWebRequest(); if (www.result != UnityWebRequest.Result.Success) { Debug.LogError("Network error: " + www.error); if (!string.IsNullOrEmpty(www.downloadHandler.text)) { Debug.LogError("Response body: " + www.downloadHandler.text); } } else { string responseBody = www.downloadHandler.text; Debug.Log("Response body: " + responseBody); text.text = responseBody; } } }
关键修改点
- 新增
GraphQLRequest类,通过JsonUtility.ToJson生成格式正确的JSON,避免手动拼接的语法错误。 - 放弃
UnityWebRequest.Post,手动构建POST请求并使用UploadHandlerRaw传递JSON字节数组,避免表单编码与JSON请求头的冲突。 - 明确设置
Accept请求头,符合GraphQL服务器的响应预期。
内容的提问来源于stack exchange,提问作者lnmr24
相关产品推荐
相关产品推荐

