12

数据传输POST心法分享,做前端的你还解决不了这个bug? - 葡萄城技术团队

 2 years ago
source link: https://www.cnblogs.com/powertoolsteam/p/16169531.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

数据传输POST心法分享,做前端的你还解决不了这个bug?

随时随地给大家提供技术支持的葡萄又来了。这次的事情是这样的,提供demo属于是常规操作,但是前两天客户突然反馈压缩传输模块抛出异常,具体情况是压缩内容传输到服务端后无法解压。

由于代码没有发生任何变动,前端相关依赖也没有升级,服务端java版本也没有变化,所以我们可以推定为环境问题;进一步仔细检查,经过反复对比后突然发现服务端收到的压缩内容变长了;和前端请求内容进行对比,发现所有的\r和\n都变成了\r\n。

综合以上分析我们初步判断:问题出在了浏览器转译之中。为了验证猜想是否正确,葡萄将chrome版本回退到92版,异常消失,服务端接收的内容也没有被替换。

问题是顺利解决了,但是Chrome POST数据内容居然会在传输过程中发生变化。一直擅长大前端技术的葡萄绝不认输,为了弄明白这一原因,我们来看看POST的细节操作到底有什么。
控制字符
首先我们需要搞清楚几个控制字符的含义。

  • 回车符(CR)和换行符(LF)是文本文件用于标记换行的控制字符(control characters)或字节码(bytecode)。
  • CR = Carriage Return,回车符号(\r,十六进制 ascii 码为0x0D,十进制 ascii 码为13),用于将鼠标移动到行首,并不前进至下一行。
  • LF = Line Feed,换行符号( \n, 十六进制 ascii 码为 0x0A,十进制 ascii 码为10)。
    紧邻的 CR 和 LF(组成 CRLF,\r\n,或十六进制 0x0D0A)将鼠标移动到下一行行首。(Windows 操作系统默认的文本换行符为 CRLF;Linux 以及 macOS 系统默认使用 LF,早期的 mac os 系统使用 CR 换行。)

在代码管理中,在不同操作系统下CRLF会有很大不同。下面在不同系统中为大家实际演示一下:
在Mac Visual Code中新建一个文档默认为LF,而Windows中为CRLF,可以选择切换行尾序列的内容的类型。

Mac版Visual Code

Windows 版

面对这种情况,需要开发者统一CRLF,以免不同操作系统开发导致代码管理的混乱。

POST传输的数据变化

弄明白了在不同系统中,控制字符会出现不同的原因,接下来我们就需要搞清楚为什么POST的数据在传输过程中发生了变化。

我们来写个简单Demo测试一下。先在页面上放一个允许换行的textarea, 输入带换行的文本,获取内容看到只有\n转译。通过FormData直接post数据到服务端,然后直接返回,看到\n全部变成了\r\n。

            var uploadData = document.getElementById("ta").value
            var formData = new FormData();
            formData.append("data", uploadData)
            fetch("http://localhost:8088/spread/getpdf", {
                    body: formData,
                    method: "POST"
                }).then(resp => resp.text())
                .then(text => {
                    console.log(JSON.stringify(text));
                    document.getElementById("result").innerHTML= JSON.stringify(text)
                })

浏览器标识:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.83 Safari/537.36

回退Chrome到92版本,发送和接收文本此时编为一致:

Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36

深入探究这一原因,我们了解到互联网请求意见稿2046(RFC 2046)4.1.1.中有明确说明:

 “ The canonical form of any MIME‘text’ subtype MUST always represent a
   line break as a CRLF sequence. “ 

这里我们可以看到所有的文本类型都要使用CRLF,而Chrome只是修复了一个“bug”,对于用户而言,在普通文本中用户感知不到CR、LF和CRLF的区别,但是当使用场景转换到解压的文本内容就变得十分重要。

三种解决方式

大家都知道POST是HTTP的一个常用方法,而另一个我们常用的方法是GET。
关于GET和POST区别以及使用相关问题这里不做赘述,要解决POTS传输的数据变化问题,最相关的是Content-Type。

首先我们来了解Content-Type和MIME分别是什么:
Content-Type,内容类型,一般是指网页中存在的Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件,这就是经常看到一些Asp网页点击的结果却是下载到的一个文件或一张图片的原因。

在POST中常用的Content-Type有application/x-www-form-urlencoded、multipart/form-data和application/json。

1、 application/x-www-form-urlencoded
将需要内容提交表单后,内容会按照name1=value1&name2=value2的方式编码,并且key和valu e都会进行URL转码。
对于"\n"和"\r" 会被转码为'%0A'和'%0D',通过这种传输方式,避免了浏览器的对CRLF的修正可以解决以上问题。
但是这样转码会增加文本长度,原本1个字符变成了3个,结果是压缩的文本又变长了。

2、multipart/form-data
当需要想服务器提交文件时,就需要使用这种方式。前面代码中我们可以看到当formData是普通文本是会被修正,为了解决这个情况我们可以将string内容封装到Blob中作为文件流传输,来避免修正。
这样传输,服务端会以文件方式收到内容,直接读取Stream内容;对于压缩文本,这种处理方式最优。

           var formData = new FormData();
            formData.append("data", uploadData)
            formData.append("data1", new Blob( [uploadData]))


上图展示了同样的内容,使用不同方式进行传输。

3、 application/json
Json也是目前比较流行的传输方式,json的内容在post传输中也不会被改变,如果文本内容不长,也是不错的方式。

          fetch("http://localhost.charlesproxy.com:8088/spread/postjson", {
                    headers: {
                        'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({data: uploadData}),
                    method: "POST"
                }).then(resp => resp.text())
                .then(text => {
                    console.log(JSON.stringify(text));
                    document.getElementById("result").innerHTML= JSON.stringify(text)
                })

作为一个前端er,除了HTML、CSS和Javascript三大件,熟练使用Axios等类库调用API,更不可忽视的是要了解如何调试网络请求,在项目出现问题时能快速定位到问题的所在。

这里提供了在 Angular 框架下动态加载js文件时返回 Content-Type 为text/html 的Demo,大家感兴趣的可以自行下载试试。

Demo 地址: https://gcdn.grapecity.com.cn/forum.php?mod=attachment&aid=NDc5OTJ8YmU1Mjk0NDN8MTY1MDI2MTI0M3wxfDUwOTgw


Recommend

  • 40

    前言 最近笔者[email protected]玄猫安全想研究了一下智能合约逆向,顺便入门一下逆向的知识,所以打算边学边写,不足之处请多指正。本篇我们就从一个题目开始看起。 题目 题目地址 :

  • 67
    • www.freebuf.com 5 years ago
    • Cache

    T-Pot多蜜罐平台使用心法

    *本文作者:R00to1,本文属 FreeBuf 原创奖励计划,未经许可禁止转载。 介绍 最近看到大佬发了几篇tpot蜜罐的文章,都是介绍安装的,那我就来写个看看怎么使用的文章,抛砖引玉,共同进步。我的蜜罐也是从16...

  • 83

    文案难以速成,只在于坚持;但是还是有帮助大家(尤其是初学者)更快掌握文案技巧的心法,一起来看下吧~ 文案有没有速成的诀窍? ——有人这样问我。 呵呵,这位同学,你把文案当什么了? “三天让你成为文案高手”、“成为李欣频这样的顶级文案只需七天”、“14天教你成...

  • 57
    • www.woshipm.com 5 years ago
    • Cache

    产品设计心法:数据看板篇

    本文作者依据工作中项目实践的所思所想,并结合案例等分享了数据看板设计过程中需要注意的一些问题,供大家一同参考和学习。 写在前面 说来惭愧,最近在页面设计上踩了不少的坑,于是想着把产品设计中遇到的问题和心得拎出来讲讲,希望能给更多的新人产品经理提供...

  • 82
    • 微信 mp.weixin.qq.com 4 years ago
    • Cache

    运维工程师心法:6 大技能让你告别背锅

    一、线上操作规范 1.测试使用 当初...

  • 17
    • www.cnblogs.com 4 years ago
    • Cache

    5L-链表导论心法

    链表是比数组稍微复杂一点的数据结构,也是两个非常重要与基本的数据结构。如果说数组是纪律严明排列整齐的「正规军」那么链表就是灵活多变的「地下党」。 关注公众号 MageByte,有你想要的精彩内容。 链表是一种物理存...

  • 25
    • www.cnblogs.com 3 years ago
    • Cache

    再解决不了前端加密我就吃shi

    参考文章 快速定位前端加密方法 ...

  • 5
    • www.51cto.com 1 year ago
    • Cache

    前端性能优化心法

    前端性能优化心法 原创 作者: Thoughtworks洞见

  • 7

    文案进阶的六大心法,这个干货有点干! 作者:

  • 6

    羊了个羊-引爆全域的社交裂变心法(分享版) Svip¥0.19

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK