HTTP请求中 request payload 和 formData 区别

一、FormData和Payload是浏览器传输给接口的两种格式,这两种方式浏览器是通过Content-Type来进行区分的。

  • application/x-www-form-urlencoded,则为formdata
  • application/json或multipart/form-data,则为 request payload

二、Content-Type
Content-Type是指 http 请求发送信息至服务器时的内容编码类型。用于表明发送数据流的类型,服务器根据编码类型使用特定的解析方式,获取数据流中的数据。

常用的Content-Type有如下:
页面资源类型:text/html, text/plain, text/css, text/javascript,
image/jpeg, image/png, image/gif

ajax&表单提交&上传文件:application/x-www-form-urlencoded, multipart/form-data, 
application/json, application/xml

三、FormData & Request Payload 的区别
注意:Request Payload更准确的说是http request的payload body
在这里插入图片描述
当POST请求的请求头里设置Content-Type: application/x-www-form-urlencoded(默认), 参数在请求体以标准的Form Data的形式提交,以&符号拼接,参数格式为key=value&key=value&key=value…

当POST请求的请求头里设置Content-Type:application/json,参数在请求体以JSON形式提交,参数格式为JSON格式{“key”:“value”,“key”:“value”…}。

HTTP请求报文由3部分组成(请求行+请求头+请求体)
在这里插入图片描述
两种提交都会将数据放在message-body的payload中,只是因为Content-Type设置的不同,并不是数据提交方式的不同,为什么有时候后端拿不到值呢?这就不得不说服务器对payload的解析方式了

四、服务器解析 POST 数据

protectedvoid parseParameters() {
      //省略部分代码......
      parameters.handleQueryParameters();// 这里是处理url中的参数
      //省略部分代码......
      if ("multipart/form-data".equals(contentType)) { // 这里是处理文件上传请求
        parseParts();
        success = true;
        return;
      }
      if(!("application/x-www-form-urlencoded".equals(contentType))) {// 这里如果是非POST请求直接返回,不再进行处理
        success = true;
        return;
      }
      //下面的代码才是处理POST请求参数
      //省略部分代码......
      try {
        if (readPostBody(formData, len)!= len) { // 读取请求体数据
          return;
        }
      } catch (IOException e) {
        // Client disconnect
        if(context.getLogger().isDebugEnabled()) {
          context.getLogger().debug(
              sm.getString("coyoteRequest.parseParameters"),e);
        }
        return;
      }
      parameters.processParameters(formData, 0, len); // 处理POST请求参数,把它放到requestparameter map中(即request.getParameterMap获取到的Map,request.getParameter(name)也是从这个Map中获取的)
      // 省略部分代码......
}
protected int readPostBody(byte body[], int len)
    throws IOException {
    int offset = 0;
    do {
      int inputLen = getStream().read(body, offset, len - offset);
      if (inputLen <= 0) {
        return offset;
      }
      offset += inputLen;
    } while ((len - offset) > 0);
    return len;
}

从上面代码可以看出,Content-Type不是application/x-www-form-urlencoded的POST请求是不会读取请求体数据和进行相应的参数处理的,即不会解析表单数据来放到request parameter map中。所以通过request.getParameter(name)是获取不到的。

五、php接收request payload的数据的方法
只能通过获取原始数据流的方式来进行解析请求数据
$data = file_get_contents( “php://input”);

<think>好的,用户遇到了Unity中的UnityWebRequestException: HTTP/1.1400Bad Request错误,需要我的帮助解决。首先,我得回顾一下之前提供的解决方案,以及用户现在给出的站内引用,看看有没有新的信息需要整合。用户提到的引用[1]指出400错误是由于请求语法有问题,服务器无法理解。引用[2][3]则是关于404错误的,可能与当前问题关联不大,但用户可能之前遇到过类似问题,所以需要确保当前解决方案覆盖了可能的语法或结构错误。 之前的回答已经涵盖了URL检查、HTTP方法、标头设置、数据格式、错误处理异步请求等方面。现在需要确认是否遗漏了其他常见原因,比如编码问题、URL参数格式不正确,或者服务器端的特定要求。 用户现在再次询问解决方案,可能意味着之前的步骤没有完全解决问题,或者需要更详细的指导。我需要考虑用户可能的操作疏漏,比如是否在POST请求中错误地使用了GET方法,或者数据序列化时未正确使用UTF-8编码。 另外,引用[3]提到了一些调试方法,比如使用模拟器或查看网络请求,可能需要建议用户使用工具如Fiddler或Wireshark来捕获请求数据,确保发送的内容符合服务器预期。还要注意用户可能在处理JSON数据时,没有正确设置Content-Type为application/json,或者缺少必要的授权头,比如BearerToken。此外,检查是否有重定向问题,因为某些服务器处理重定向时可能引发400错误。 最后,需要强调错误日志的重要性,建议用户查看Unity的调试输出服务器日志,以获取更具体的错误信息。如果用户已经尝试了所有步骤仍未解决,可能需要联系后端团队协助排查。</think>### UnityWebRequest 400 Bad Request 错误解决方案 遇到 `UnityWebRequestException: HTTP/1.1 400 Bad Request` 错误时,表明服务器认为客户端请求存在语法或结构问题。结合引用[^1]中提到的“请求格式错误”问题,以下是针对 Unity 的具体排查修复步骤: --- #### 1. **检查请求语法完整性** - **URL 合法性**:确保 URL 包含协议(`http://` 或 `https://`)且无特殊字符(如空格或中文需编码)。 ```csharp string url = "https://api.example.com/data?param1=value1"; // 检查参数是否合法 ``` - **HTTP 方法匹配**:若服务器要求 POST 请求,但代码中使用 GET,则会触发 400 错误[^1]。 ```csharp UnityWebRequest request = UnityWebRequest.Post(url, formData); // 明确使用 POST 方法 ``` --- #### 2. **验证请求内容类型** - **强制指定 Content-Type**:若未设置 `Content-Type`,服务器可能无法解析请求体。 ```csharp request.SetRequestHeader("Content-Type", "application/json"); // 明确数据类型[^1] ``` - **添加必要标头**:如身份验证令牌或 API 版本号。 ```csharp request.SetRequestHeader("Authorization", "Bearer " + accessToken); ``` --- #### 3. **确保数据序列化正确** - **JSON 格式验证**:使用 `JsonUtility.ToJson()` 序列化对象时,需确保字段命名与服务器要求一致。 ```csharp MyData data = new MyData { id = 1, name = "test" }; string json = JsonUtility.ToJson(data); // 检查序列化结果是否符合预期 ``` - **编码一致性**:请求体需使用 UTF-8 编码,避免特殊字符错误。 ```csharp byte[] bodyRaw = Encoding.UTF8.GetBytes(json); request.uploadHandler = new UploadHandlerRaw(bodyRaw); ``` --- #### 4. **捕获并分析错误详情** - **输出完整响应内容**:服务器可能在响应体中返回具体错误原因。 ```csharp yield return request.SendWebRequest(); if (request.result != UnityWebRequest.Result.Success) { Debug.LogError($"状态码: {request.responseCode} | 错误详情: {request.downloadHandler.text}"); } ``` - **使用网络调试工具**:通过 Fiddler 或浏览器开发者工具捕获原始请求,对比与服务器文档的一致性[^1]。 --- #### 5. **服务器端协作排查** - **比对 API 文档**:确认参数类型(如字符串需引号包裹)、必填字段是否遗漏。 ```json // 错误示例:未包裹字符串值 { "id": 1, "name": test } // 正确示例 { "id": 1, "name": "test" } ``` - **检查服务器日志**:若问题持续,联系后端开发人员查看服务器接收的原始请求数据。 --- ### 示例代码(修复版) ```csharp using UnityEngine; using UnityEngine.Networking; using System.Text; using System.Collections; public class WebRequestExample : MonoBehaviour { public IEnumerator SendPostRequest() { string url = "https://api.example.com/endpoint"; MyData data = new MyData { userId = 123, action = "submit" }; string json = JsonUtility.ToJson(data); byte[] payload = Encoding.UTF8.GetBytes(json); UnityWebRequest request = new UnityWebRequest(url, "POST"); request.uploadHandler = new UploadHandlerRaw(payload); request.downloadHandler = new DownloadHandlerBuffer(); request.SetRequestHeader("Content-Type", "application/json"); request.SetRequestHeader("Authorization", "Bearer xyz123"); yield return request.SendWebRequest(); if (request.result == UnityWebRequest.Result.ProtocolError) { Debug.LogError($"400 错误详情: {request.downloadHandler.text}"); } else { Debug.Log($"响应内容: {request.downloadHandler.text}"); } } } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值