zoukankan      html  css  js  c++  java
  • 浏览器有别_HTTP报文的回车换行

    本来以为浏览器HTTP报文的生成应该是完全一致的。但最近在做一个项目的时候,发现Safari和Chrome提交同一份表单,后端的处理结果不一致。看提交结果呢,是因为Safari多了个回车。由于原项目的提交数据比较复杂,我就写了简单的测试来加以验证。

    说是测试,其实也是验证心里的想法:正常的HTTP报文每行结尾符一般用 ,那如果我提交的文本里面带了 ,那浏览器会不会主动补充成 呢?

    从现在的情况来看,Safari是会主动补充成 ,而谷歌不会。接下来就来测试一下。

    测试前的准备

    一、准备一个测试用的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;urlencoded会进行url编码, 就是%0a,也不是换行;而form-data的换行就是换行。

    三、选择测试工具

    我用的是Charles,用起来比起直接在浏览器看报文更加自由一点。

    我平时主要是爬虫需要进行模拟登录时或者爬取手机端时,用它来分析请求报文。

    简书上的一篇教程

    开始测试

    一、编写测试脚本

    1. application/json格式的请求

      var xhr = new XMLHttpRequest;
      xhr.open("post", "/browser/returntest");
      xhr.setRequestHeader("Content-Type", "application/json");
      xhr.send(JSON.stringify({
        str: "abc
      abc"
      }));
      // # 等效于
      // curl -H "Content-Type: application/json" -X POST --data '{"str":"abc
      abc"}' http://localhost:3030/browser/returntest
      
    2. 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
      abc");
      // # 等效于
      // curl -H "Content-Type: application/x-www-form-urlencoded" -X POST --data 'str=abc
      // abc' http://localhost:3030/browser/returntest
      
    3. multipart/form-data格式的请求

      var xhr = new XMLHttpRequest;
      var formData = new FormData
      formData.append("str", "abc
      abc");
      xhr.open("post", "/browser/returntest");
      xhr.send(formData);
      // # 等效于
      // curl -H "Content-Type: multipart/form-data" -X POST --form 'str=abc
      // abc' http://localhost:3030/browser/returntest
      

    二、测试

    1. 启动Nodejs Web服务;
    2. 打开浏览器,输入http://localhost.charlesproxy.com:3030/browser/returntest
    3. 打开Charles;
    4. 打开浏览器控制台,输入脚本进行测试。

    三、测试结果

    1. 提交application/json请求(谷歌、Safari结果一致)

      把application/json格式的请求输入到控制台,可以在Charles截获到请求:

      image-20211021133155120

      此时nodejs的输出为:

      image-20211021133239152

      Charles可以看到请求报文的数据是:

      image-20211021133320495

      Charles可以看到请求体的十六进制表示是:

      image-20211021133423434

      可以看到, 就是n对应5cn对应6e。(想确认ASCII码的可以看对照表

      application/json测试验证猜想,json数据字符串经过转义后 就是\n,本来就不是换行,而是反斜杠和字母n。

    2. 提交application/x-www-form-urlencoded请求(谷歌、Safari结果一致)

      把application/x-www-form-urlencoded格式的请求输入到控制台,可以在Charles截获到请求。

      此时nodejs的输出为:

      image-20211021133239152

      Charles可以看到请求报文的数据是:

      image-20211021134403736

      Charles可以看到请求体的十六进制表示是:

      image-20211021134424754

      这和猜想的倒是有些不一样,xhr.send的时候没有把换行按urlencoded的格式转成%0A,而是以换行的形式传输。更让我意想不到的是,这次Safari也没有在换行前加上回车了,我本来以为Safari补回车或换行是为了严谨性,结果太让人失望了。

    3. 提交application/x-www-form-urlencoded请求的补充测试(谷歌、Safari结果一致)

      xhr.send不行,也许是application/x-www-form-urlencoded格式的数据大多数时候是以表单形式直接提交的吧,那我通过表单直接提交试一下。

      image-20211021135607282

      此时在Charles截获到请求:

      image-20211021135637049

      请求体的十六进制表示是:

      image-20211021135739035

      这次编码了,但是回车(%0D)也给加上了是什么鬼,谷歌也是一样的,这难道是浏览器统一的标准.

      我直接在本地复制一段只有换行的文本呢?好吧,也是一样的。

      综上,通过浏览器表单输入的多行文本多会被补全成

      nodejs的输出都为:

      image-20211021140223256

    4. 提交multipart/form-data请求(谷歌、Safari结果不一致)

      • 谷歌

        把multipart/form-data格式的请求输入到控制台,可以在Charles截获到请求。

        此时nodejs的输出为:

        image-20211021133239152

        Charles可以看到请求报文的数据是:

        image-20211021140612198

        Charles可以看到请求体的十六进制表示是:

        image-20211021140837073

        谷歌测试验证猜想,abc和abc之间只有换行(0a)。

      • Safari

        把multipart/form-data格式的请求输入到控制台,可以在Charles截获到请求。

        此时nodejs的输出为:

        image-20211021140223256

        Charles可以看到请求报文的数据是:

        image-20211021141453728

        Charles可以看到请求体的十六进制表示是:

        image-20211021141725023

        Safari测试验证猜想,abc和abc之间补充上回车(0d)。

        除此之外,我还测试了 上传会不会补充 ,结果也是会的。

    测试小结

    实验证明,如果以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
    abc"));
    // # 等效于
    // curl -H "Content-Type: application/x-www-form-urlencoded" -X POST --data 'str=abc%0aabc' http://localhost:3030/browser/returntest
    

    然后这次测试还不完善,像以multipart/form-data数据格式上传带回车或换行的文件是否会有问题没有测,响应体是否也会被补充成回车换行没有测。有兴趣大家自己测一测吧。

    试探性地留下名字
  • 相关阅读:
    springcloud学习(五)之GateWay
    springcloud学习(四)之Feign
    springcloud学习(三)之Hystrix
    springcloud学习(二)之Ribbon
    springcloud学习(一)之Eureka
    关于ES6尾调用优化
    CSS常考知识点
    Chrome动画调试最佳实践
    HTML常考知识点
    代码之旅:基础规范
  • 原文地址:https://www.cnblogs.com/xuanyu-10-18/p/15434208.html
Copyright © 2011-2022 走看看