浏览器有别_HTTP报文的回车换行
本来以为浏览器HTTP报文的生成应该是完全一致的。但最近在做一个项目的时候,发现Safari和Chrome提交同一份表单,后端的处理结果不一致。看提交结果呢,是因为Safari多了个回车。由于原项目的提交数据比较复杂,我就写了简单的测试来加以验证。
说是测试,其实也是验证心里的想法:正常的HTTP报文每行结尾符一般用
\r\n,那如果我提交的文本里面带了
\r或
\n,那浏览器会不会主动补充成
\r\n呢?
从现在的情况来看,Safari是会主动补充成
\r\n,而谷歌不会。接下来就来测试一下。
测试前的准备
一、准备一个测试用的Web服务
const Koa = require('koa'); const koaBody = require('koa-body'); const Router = require("koa-router"); const router = new Router(); const app = new Koa(); app.use(koaBody({ multipart: true })); router.get("/browser/returntest", (ctx) => { ctx.status = 200; ctx.body = "<form method='post' action='/browser/returntest'><textarea name='str'></textarea><button type='submit'></button></form>"; }); router.post("/browser/returntest", (ctx) => { console.log(ctx.request.body) ctx.status = 200; ctx.body = { isSuccessful: true, data: "post,成功", errCode: 0 }; }); app.use(router.routes()).use(router.allowedMethods()); app.listen(3030);
二、选定测试参数
这次测试主要选定了几个可以上传键值对的Content Type,分别是application/json、application/x-www-form-urlencoded、multipart/form-data。
按理来说:json数据字符串经过转义后
\n就是
\\n,本来就不是换行,而是反斜杠和字母n;urlencoded会进行url编码,
\n就是
%0a,也不是换行;而form-data的换行就是换行。
三、选择测试工具
我用的是Charles,用起来比起直接在浏览器看报文更加自由一点。
我平时主要是爬虫需要进行模拟登录时或者爬取手机端时,用它来分析请求报文。
开始测试
一、编写测试脚本
-
application/json格式的请求
var xhr = new XMLHttpRequest; xhr.open("post", "/browser/returntest"); xhr.setRequestHeader("Content-Type", "application/json"); xhr.send(JSON.stringify({ str: "abc\nabc" })); // # 等效于 // curl -H "Content-Type: application/json" -X POST --data '{"str":"abc\nabc"}' http://localhost:3030/browser/returntest
-
application/x-www-form-urlencoded格式的请求
var xhr = new XMLHttpRequest; xhr.open("post", "/browser/returntest"); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send("str=abc\nabc"); // # 等效于 // curl -H "Content-Type: application/x-www-form-urlencoded" -X POST --data 'str=abc // abc' http://localhost:3030/browser/returntest
-
multipart/form-data格式的请求
var xhr = new XMLHttpRequest; var formData = new FormData formData.append("str", "abc\nabc"); xhr.open("post", "/browser/returntest"); xhr.send(formData); // # 等效于 // curl -H "Content-Type: multipart/form-data" -X POST --form 'str=abc // abc' http://localhost:3 3ea0 030/browser/returntest
二、测试
- 启动Nodejs Web服务;
- 打开浏览器,输入
http://localhost.charlesproxy.com:3030/browser/returntest
; - 打开Charles;
- 打开浏览器控制台,输入脚本进行测试。
三、测试结果
-
提交application/json请求(谷歌、Safari结果一致)
把application/json格式的请求输入到控制台,可以在Charles截获到请求:
此时nodejs的输出为:
Charles可以看到请求报文的数据是:
Charles可以看到请求体的十六进制表示是:
可以看到,
\n
就是\
和n
,\
对应5c
,n
对应6e
。(想确认ASCII码的可以看对照表)application/json测试验证猜想,json数据字符串经过转义后
\n
就是\\n
,本来就不是换行,而是反斜杠和字母n。 -
提交application/x-www-form-urlencoded请求(谷歌、Safari结果一致)
把application/x-www-form-urlencoded格式的请求输入到控制台,可以在Charles截获到请求。
此时nodejs的输出为:
Charles可以看到请求报文的数据是:
Charles可以看到请求体的十六进制表示是:
这和猜想的倒是有些不一样,xhr.send的时候没有把换行按urlencoded的格式转成%0A,而是以换行的形式传输。更让我意想不到的是,这次Safari也没有在换行前加上回车了,我本来以为Safari补回车或换行是为了严谨性,结果太让人失望了。
-
提交application/x-www-form-urlencoded请求的补充测试(谷歌、Safari结果一致)
xhr.send不行,也许是application/x-www-form-urlencoded格式的数据大多数时候是以表单形式直接提交的吧,那我通过表单直接提交试一下。
此时在Charles截获到请求:
请求体的十六进制表示是:
这次编码了,但是回车(%0D)也给加上了是什么鬼,谷歌也是一样的,这难道是浏览器统一的标准.
我直接在本地复制一段只有换行的文本呢?好吧,也是一样的。
综上,通过浏览器表单输入的多行文本多会被补全成
\r\n
。nodejs的输出都为:
-
提交multipart/form-data请求(谷歌、Safari结果不一致)
谷歌
把multipart/form-data格式的请求输入到控制台,可以在Charles截获到请求。
此时nodejs的输出为:
Charles可以看到请求报文的数据是:
Charles可以看到请求体的十六进制表示是:
谷歌测试验证猜想,abc和abc之间只有换行(0a)。
-
Safari
把multipart/form-data格式的请求输入到控制台,可以在Charles截获到请求。
此时nodejs的输出为:
Charles可以看到请求报文的数据是:
Charles可以看到请求体的十六进制表示是:
Safari测试验证猜想,abc和abc之间补充上回车(0d)。
除此之外,我还测试了
\r
上传会不会补充\n
,结果也是会的。
测试小结
实验证明,如果以multipart/form-data数据格式上传带回车或换行的数据,在Safari里会补充成回车换行,而Chrome不会。如果不要回车换行其中的一个,后端还要做校验才是。
这次实验我本来以为Safari补全成回车换行是更严谨的做法,但它这做事做一半就让人很不舒服,要补把application/x-www-form-urlencoded格式的数据也补了嘛。不过从合理性上考虑,毕竟叫urlencoded,我们做数据请求的时候还是要自己做一个编码。
var xhr = new XMLHttpRequest; xhr.open("post", "/browser/returntest"); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send(encodeURI("str=abc\nabc")); // # 等效于 // curl -H "Content-Type: application/x-www-form-urlencoded" -X POST --data 'str=abc%0aabc' http://localhost:3030/browser/returntest
然后这次测试还不完善,像以multipart/form-data数据格式上传带回车或换行的文件是否会有问题没有测,响应体是否也会被补充成回车换行没有测。有兴趣大家自己测一测吧。
- 浏览器禁用退格键和回车,文本区域支持回车换行 IE6,Firefox2.X,Firefox3.x版本下测试通过
- 学生A希望访问网站www.ss.edu.cn,用户A在其浏览器中输入http://www.ss.edu.cn并按回车,直到西亚斯的网站首页显示在其浏览器中,请问:在此过程中,按照TCP/IP参考模型,
- php json字符串中回车换行浏览器没解析
- HTTP工作过程(浏览器地址栏键入URL按下回车发生了什么?)
- textarea 通过 json在各浏览器的显示回车换行的问题
- j2ee的web项目,在浏览器中发起一个该项目中html页面的绝对地址,也是发起的一个http url请求,请求的响应报文的结果就是该html页面的所有html代码
- 安装tomcat后,运行bin目录下的startup.bat后,启动浏览器在地址栏输入http://localhost:8080回车后显示不了tomcat页面的原因
- 终于记住回车和换行cr lf的来由和含义了 -参考: http://www.cnblogs.com/me115/archive/2011/04/27/2030762.html
- 在浏览器输入一个网址,如http://www.taobao.com,按回车之后发生了什么?
- 当你在浏览器输入一个网址,如http://www.taobao.com,按回车之后发生了什么?请从技术的角度描述,如浏览器、网络(UDP、TCP、HTTP等),以及服务器等各种参与对象上由此引发的一系
- 当你在浏览器输入一个网址,如http://www.taobao.com,按回车之后发生了什么?
- 用正则表达式替换不规则的回车换行。(C#)
- 回车与换行
- 解决输入文件中(如txt)回车换行的方法
- 计算机中换行(LF)和回车(CR)
- http mimetype为multipart/x-mixed-replace报文
- js,jquery 去除首尾空格 回车 换行
- 回车与换行的区别
- java HttpURLConnection 模拟发送浏览器请求
- php include 语句包含文件时,浏览器多出换行