由Http Post提交遇到的一个坑,深入详解4种Post发送数据编码方式

阅读引导

1、Http post的4中提交方式详解

2、遇到的一个较深的坑,以及解决思路。

最近团队的某个项目遇到一个诡异的问题。

通过生产应用程序调用客户的服务时,报错500.

但是,通过Postman模拟报文发送相同,却返回正确。

难点在于客户的生产程序没有打日志……据了解,客户使用的是C#开发,开发人员已经交接过多次,无法确认程序问题。

不过幸好,这个客户提供的服务通信协议是Http。也就是说,可以通过网络抓包解决。

1

解决路径

由于是客户报错500,而对方又不配合排查,且程序没有打印日志,只能猜测那个地方可能出问题。(苦逼的乙方)

一个大背景是在去年,双方已经在测试环境经过了验证,然后投产了。

但是双方程序员都坚称自己没有改动过程序……

经过一系列的混乱后,制定了解决路径方法。

首先,业务协调客户开发人员加上日志,在晚上配合临时替换生产程序,查出到底是哪里报错。

其次,生产环境抓包,本地互联网环境也抓postman 的发送请求报文,比较异同点。(幸好对方是http)

2

问题原因

由于开发环境管控,开发人员进行postman发送,并安装wireshark抓包,进展缓慢。

幸而,客户方面取得突破。

上线日志打印之后,终于发现问题。

客户程序对于Http请求报文序列化之后,得到的参数有一些是空,但是我方发送报文明明是发送了参数。

然后,客户又在处理Http报文的入口,进来就打印程序,发现所有的参数全部都存在。

因此,怀疑是客户那边自己的程序出了问题。

但是,后来客户坚称没有改动,也不愿因此改动。

比对了一些Http请求报文后,发现入口程序打印的请求参数部分类似这样:&syscode&transcode=12345

客户开发人员称:对方是C#的处理框架,对于参数为空的方式,也必须送“=”,也就是说,上面部分的内容应该是:&syscode**=**&transcode=XR10010

作为乙方,只好再次去适配客户解决。在发送Http post请求的时候,对所有的参数做了判空处理,空值参数不再发送给客户。

3

HttpClient对于此方式的处理

在解决了生产问题之后,反过来去研究对于Http请求,到底是怎么回事。

应用程序调用的是HttpClient4.5.3 发现,底层对于:content type是application/x-www-form-urlencoded的编码提交方式,有处理判断。

如果是空值,则不拼接“=”。

主要是:URLEncodeUtils.java

其中主要逻辑代码如下,其中:NAME_VALUE_SEPARATOR 就是 “=”

if(encodedValue!=null){

result.append(NAME_VALUE_SEPARATOR);

result.append(encodedValue);

}

4

HTTP的四种Post提交编码发送方式

HTTP协议规范把HTTP的请求分为三部分:状态行、请求头、消息主体。

应用开发提交的数据,一般需要放在消息主体(entity-body)中(对于请求头中的内容,一般不做变更,但是有一些开发规范会要求在请求头中放签名字段),但是对于entity-body中的内容具体用什么编码方式,协议并没有规定。

所以,需要在Http的请求头中,指定编码方式,使得客户端与服务器端进行协商。

对于Post请求来说,编码方式一般分为四种:

application/x-www-form-urlencoded

这是最常见的编码方式,首先,Content-Type 被指定为 application/x-www-form-urlencoded;其次,提交的数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。 大部分服务端语言都对这种方式有很好的支持。

按照HTTP的报文协议规范,发送的请求长成这个样子:

POST http://www.test.com  HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3`

multipart/form-data

我们使用表单上传文件时,必须让 表单的enctype 等于 multipart/form-data

application/json

这种情况想,发送上面的同样的请求,http报文为:

POST http://www.test.com  HTTP/1.1
Content-Type: application/json;charset=utf-8{"title":"test","sub":[1,2,3]}

text/xml

POST http://www.example.com HTTP/1.1
Content-Type: text/xml<?xml version="1.0"?>
<methodCall>
<methodName>examples.getStateName</methodName>
<params>
<param>
<value><i4>41</i4></value>
</param>
</params>
</methodCall>

5

实际应用开发

已经知道了POST提交的四种方式,那么实际应用中该怎么使用呢?

当前,用的比较多的是:application/x-www-form-urlencodedapplication/json

只不过,在实际开发中,请求中的报文肯定都是密文的,甚至可能都同时传递签名串。

那么,对于application/x-www-form-urlencoded,其报文可能是这样:

POST http://www.test.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8

signstr=5est&body=8iejkuopui`

对于application/json

其报文可能是这样:

POST http://www.test.com HTTP/1.1
Content-Type: application/json;charset=utf-8

{“signstr”:“5est”,“body”:“8iejkuopui”}

服务端的web服务器对Http报文体,根据content-type解析后,再传递给应用。

应用程序就可以再去解析响应字段,做解密验签等操作了。

6

Http编码传输

刚才说了,content-type属性,指的是报文体的报文协议编码方式。

那么,我们知道报文是以字节的方式进行网络传输的,整个Http的请求,有没有编码呢?

答案是肯定的。

Http自带的内容还是比较多的,在报文较小的情况下,尤为明显。

这也是Http规范向Http2、3演进的原因。

也是分布式微服务架构,大多使用RPC方式的一个原因点。

为了提升传输速度,减小带宽占用,肯定要对http报文进行编码压缩。

内容编码有如下几种,一般是在请求头上加上:Accept-Encoding;在响应头中加上 Content-Encoding;

gzip(GNU zip)

compress(UNIX系统的标准压缩)

deflate(zlib)

identity(不进行编码)

由Http Post提交遇到的一个坑,深入详解4种Post发送数据编码方式相关推荐

  1. python避坑_Django搭建项目实战与避坑细节详解

    Django 开发项目是很快的,有多快?看完本篇文章,你就知道了. 安装 Django 前提条件:已安装 Python. Django 使用 pip 命令直接就可以安装: pip install dj ...

  2. 超级棒的一个DP问题详解(入门)

    超级棒的一个DP问题详解(入门) 只要耐心看肯定可以理解的~动态规划问题故事描述~ 通过金矿模型介绍动态规划 附上原文地址: http://www.cnblogs.com/sdjl/articles/ ...

  3. python编写一个名片_详解Python做一个名片管理系统

    名片管理系统有两个模块组成:cards_main.py和 cards_tools.py一个是主程序,另一个是封装增删改查函数的被调用程序 代码如下 cards_main.py #! /usr/bin/ ...

  4. Java基础【之】输出一个菱形(详解)

    Java基础[之]输出一个菱形(详解) 代码示例 <目录:Java渐进式学习> <目录:Java设计模式> <目录:从零手写Tomcat> 代码示例 public ...

  5. Java程序员从笨鸟到菜鸟之(五十一)细谈Hibernate(二)开发第一个hibernate基本详解...

    在上篇博客中,我们介绍了<hibernate基本概念和体系结构>,也对hibernate框架有了一个初步的了解,本文我将向大家简单介绍Hibernate的核心API调用库,并讲解一下它的基 ...

  6. Git(7)-- 查看提交历史(git log 命令详解)

    文章目录 1.`git clone` 2.`git log` 3.`git log -p` 4.`git log --stat` 5.`git log --pretty=oneline` 6.`git ...

  7. 【git 整理提交】git rebase -i 命令详解

    git rebase -i 详解 官方文档 变基时可用的命令 变基时有六个命令可用: pick pick只是意味着包括提交.重新进行命令时,重新安排pick命令的顺序会更改提交的顺序.如果选择不包括提 ...

  8. Dragger 2遇到的坑 Dragger2详解 Dragger2学习最好的资料

    我是曹新雨,我为自己代言.现在的菜鸟,3年以后我就是大神.为自己加油.微信:aycaoxinyu Dragger2是什么,我就不再说了.资料一堆,而且里面的注解什么意思,我推荐两篇文章,这两篇都是我精 ...

  9. Linux中搭建一个ftp服务器详解

    来源:Linux社区  作者:luzhi1024 详解Linux中搭建一个ftp服务器. ftp工作是会启动两个通道: 控制通道 , 数据通道 在ftp协议中,控制连接均是由客户端发起的,而数据连接有 ...

最新文章

  1. Java 详解 JVM 工作原理和流程
  2. idea常用的快捷键
  3. 7-5 排列的字典序问题 (10 分)(思路加详解全排列问题+vector容器做法)Come Baby!
  4. c语言 函数的参数传递示例_restder()函数,带有C ++中的示例
  5. Spring AOP 的切点切在Controller上没有起作用的问题。
  6. 疑似禁令影响开始显现:华为Mate 40量产或被迫推迟
  7. 2016.08.30~2017.07.20
  8. C#参考:Linq 概述
  9. (2022.9)raspberry 4安装HP 1020 plus打印机,利用树莓派4制作无线打印服务器
  10. 关于WES7的系统还原与恢复
  11. 几个可以免费下载视频素材的网站[国外],希望大家喜欢[可以的话给个关注哟]
  12. Spring包含JAR的详解
  13. 【NOTE】python3.6下scons运行提示找不到SCons.Script解决方式
  14. 第六章(项目进度管理)知识点
  15. 弹出表情气泡仿魔兽的技能冷效果却实现
  16. C++打造植物大战僵尸辅助!附完整项目源码
  17. 05【React再造之旅】从零实现一个React(下)
  18. 软件产品案例分析——福州大学微信小程序
  19. python opencv如何读取透明png图片以及如何编辑透明度
  20. C#桌面程序设计复习

热门文章

  1. sqlserver:使用 SqlBulkCopy 批量插入数据
  2. 使用卡尔曼滤波实现单目标跟踪过程中的目标运动轨迹预测
  3. 平台活动免费送,免费领取1个月优酷/爱奇艺/腾讯视频会员
  4. oracle数据库中nvarchar,Oracle数据库中的varchar,varchar2,nvarchar,nvarchar2区别及用
  5. 如何在一个APP内检测手机内安装了另外一个APP并且跳转到另外一个APP内?
  6. xtrabackup参数详解
  7. HTML5 Canvas标签
  8. linux一键安装php环境
  9. 资本寒冬来临,美图的增长引擎如何发动?
  10. Java在OJ平台提交的方式与基本套路