GET请求里的body问题

2023-11-12

故事还得从一个bug说起。今天有人问我,为什么发到后端的请求400了,我说肯定是参数不对,你去检查检查GET、POST之类的方法写没写对,要么就是字段没对上,无非是这几个问题。然后他说检查过了,没问题啊;我不太相信,但是看了看前端发送的请求,好像确实没啥问题:

我说既然这样,那肯定是后端写错了,但后端说他已经用postman测过了,肯定没问题。这就很有意思了。于是我要来了后端的代码:
不出所料,后端把GET请求里的参数当成body的内容了,把@RequestBody改成@RequestParam应该就没问题了;改完之后果然好了。

这本来是一个很简单的问题,没什么可说的,但是他们接着问我,为什么GET请求里不能用body?我寻思着平时也没什么人在GET请求里加body吧,而且一直以来都听说这么用不好。但是为什么不好呢?所以我就查了一些资料,最后干脆又去RFC翻了翻。看到官方是这么说的:

[RFC7231] A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.

意思是你往GET请求里加body是不符合规范的,不保证所有的实现都支持(主要是以前的实现,因为以前曾经有相应的规定),要是出了啥问题别怪我没提醒你。而且据说老版本的postman是不支持在GET请求里加body的,也是最近才加上的支持;所以要放在以前也就没这些问题了,以前的postman根本发不了带body的GET请求

但是这一条并不是强制规定。我看很多人都强调一点,GET请求不应携带请求体,服务器应忽略(或者说丢弃)GET请求的请求体。这一条的确是有依据的,来源如下:

[RFC2616] A server SHOULD read and forward a message-body on any request; if the request method does not include defined semantics for an entity-body, then the message-body SHOULD be ignored when handling the request.

当然,官方也只是说SHOULD,没有像前文一样措辞严厉地强调类似HEAD这种的请求MUST NOT have a message body:

[RFC2616] A message-body MUST NOT be included in a request if the specification of the request method does not allow sending an entity-body in requests.

但是很可惜的是,RFC2616已经过时了。现在的说法变成了这样,连SHOULD都直接去掉了,要求更加宽松:

[RFC7230] Request message framing is independent of method semantics, even if the method does not define any use for a message body.

难道是因为错的人多了,错的也变成了对的?不过即使是这样,也并不是在GET请求里加上body的理由。

这个问题算是解决了。但是我看到网上各路大神说到GET加body的时候,还提到一个,就是往GET里加body会导致缓存机制失效。“GET 被设计来用 URI 来识别资源,如果让它的请求体中携带数据,那么通常的缓存服务便失效了,URI 不能作为缓存的 Key。”我一开始以为是在服务器上配置的缓存,比如Nginx的cache之类的机制,后来发现好像并非如此。这个缓存,大概是指那种预加载和后存储,会涉及到一个网络请求的“安全性”。如果不安全,显然是不能缓存的。

那么,GET和POST的区别和应用?这问题挺复杂。简而言之,就是“安全”和“不安全”的区别。什么是安全?不用承担责任。什么是不安全?可能需要承担责任。举个例子,点击某个链接以同意某个协议,这个请求明显就是不安全的,因为需要承担责任。如果采用GET,就违反了GET应该用于安全请求的规范。因为浏览器可能在你不知情的情况下预加载这个页面(因为是“安全”的GET请求),这样相当于你在不知情的情况下同意了某个协议,这显然是我们不希望看到的。在契约式的设计里,违反契约的行为是会带来严重的后果的。浏览器按照契约预加载了安全的GET请求,但这本身是不安全的,带来的后果自然要由打破契约的人承担(将这个请求设计成GET的人出来挨打)。

之所以强调“安全”,而不是按照常规的说法强调副作用,因为有副作用的请求不代表不安全;举例来说,服务器有一个显示访问人数的功能,这个功能就可以用GET来做。虽然每次访问都会发送改变服务器状态(计数器)的请求,但用户不会因为这个请求承担责任,这个请求是安全的。至于什么GET请求的URL有长度限制(后来事实证明其实没有),什么GET请求的URL里不能有中文(或者说非ASCII吧),都只是实现上的区别;从最初的设计上来说区别并不在这里。

当然,这些都是纯粹的理论层面的东西。如果遵守RESTful的规范,采用语义化的GET/POST请求,自然也就不会有这些问题了。因为通常来说,查询是安全的;这也是GET的主要作用。

说起来也挺有意思的,学习了这么久,经常提起RFC,也没搞清楚RFC究竟是个啥玩意,这次就一并查了。虽然我总觉得这是受到6f名词解释的影响……原来是叫“Request For Comments”。

参考文章(不分先后):

不再以讹传讹,GET和POST的真正区别
HTTP GET with request body
谁说 HTTP GET 就不能通过 Body 来发送数据呢?
URIs, Addressability, and the use of HTTP GET and POST
此外,'URIs, Addressability, and the use of HTTP GET and POST’这篇文章我翻译成了中文,欢迎各位阅读并指正;翻译水平实在有限,只能说“尽最大努力交付”。
--------------------- 
作者:元无心 
来源:CSDN 
原文:https://blog.csdn.net/HermitSun/article/details/89889743 
版权声明:本文为博主原创文章,转载请附上博文链接!

转载于:https://my.oschina.net/airship/blog/3081424

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

GET请求里的body问题 的相关文章

  • ABB 120 六轴机械手臂编程调试(三)

    下一步进行机械手臂的程序编写 程序只是进行简单的点位运动 实现抓取功能 程序控制的点位表 输入点位 点位描述 输出点位 点位描述 DI5 夹取完成 DO5 夹取物料 DI6 放料完成 DO6 放下物料 DI7 回原点 DO7 设备就绪 DI
  • Python练习——基础练习题2

    因为控制台会让不断输入 索性就把input放到注释里了 这一片主要练习if判断和while循环 初级 判断下列语句的打印结果 1 print True and True or True 2 print True and True or Fa
  • 因果图分析法例子

    某软件规格说明书包含这样的要求 第一列字符必须是A或B 第二列字符必须是一个数字 在此情况下进行文件的修改 但如果第一列字符不正确 则给出信息L 如果第二列字符不是数字 则给出信息M 解答 1 根据需求 分析出原因和结果如下 原因 1 第一
  • smbms(超市管理系统)源码 + 分析

    在项目开始之前 我们首先要对项目的整体架构分析一下 该项目一共分为四个模块 登录注销 用户管理 订单管理 供应商管理 其中用户管理 订单管理以及供应商管理都是需要对数据库进行crud的 项目的整体架构图如下 1 前期准备 1 项目架构 2
  • Android中Activity跳转到具体的Fragment的方法

    1 首先在需要跳转的Activity写此代码 Intent intent new Intent from MainActivity class intent addFlags Intent FLAG ACTIVITY SINGLE TOP
  • 理解Android上下文Context

    Context使用场景总的来说分为两大类 使用Context调用方法 比如启动Activity 访问资源 调用系统级服务等 调用方法时传入Context 比如弹出Toast 创建Dialog等 Activity Service和Applic
  • 安装snownlp报错 error: subprocess-exited-with-error

    安装snownlp报错error subprocess exited with error 解决方案重新安装importlib metadata pip uninstall importlib metadata pip install im
  • Zabbix监控平台部署实验——自定义zabbix监控项目

    Zabbix系列文章目录 第一章 Zabbix5 0版本的安装教程 第二章 Zabbix监控平台部署实验 自定义zabbix监控项目 目录 Zabbix系列文章目录 前言 二 操作步骤 1 安装配置环境 2 授权zabbix server可
  • STM32HAL库的基本使用(1)- GPIO引脚配置

    前言 作者使用的是STM32L431RCT的开发板 Cortex M4的内核 是大学老师教学用的 原理图如下 原理图下载链接 https pan baidu com s 1c8WFBO9bPxarzaOKqDrl0Q pwd 6666 提取

随机推荐

  • Android中Recycler网格布局管理器GridLayoutManager用法

    使用RecyclerView可以制作出类似GridView的样式 但比GridView更加强大 这里我们就介绍一下RecyclerView和GridLayoutManager结和的用法 1 GridLayoutManager常用方法 构造函
  • ROS:开机自启动

    Ubuntu14 04 网上很多资料说在 etc rc local中添加脚本 实验之后完全没用 可能是系统版本不对 解决 Ubuntu14 04 开机项命令 gnome session properties 点击 add name 名字 c
  • mysql count(*)、count(1) 、count(列名)、count(distinct expr)

    文章目录 概述 优化 MyISAM InnoDB 参考文档 https dev mysql com doc refman 8 0 en group by functions html function count 概述 count 为 SQ
  • 蓝桥杯每日一题2023.9.8

    蓝桥杯2023年第十四届省赛真题 飞机降落 C语言网 dotcpp com 题目描述 N 架飞机准备降落到某个只有一条跑道的机场 其中第 i 架飞机在 Ti 时刻到达机场上空 到达时它的剩余油料还可以继续盘旋 Di 个单位时间 即它最早 可
  • Learning Video Object Segmentation from Static Images

    Abstract 论文灵感来源于 实例分割和目标跟踪 特点 1 我们的模型在每帧的基础上进行 并由前一帧的输出导向下一帧中的关注对象 2 一个高度准确的视频目标分割可以用一个卷积神经网络并用静态的图片来训练 3 使用在线和离线的策略 前者产
  • 为什么那么多的人选择到Java培训机构学习

    目前IT行业Java编程是最炙手可热的技术 Java应用范围广泛 企业在大量招收Java人才 薪水也随之上涨 发展前景越来越好 因此现在有越来越多的人发现了这片美丽的新大陆 都正在拼命往里的挤 一些觉得Java培训机构费用贵的同学会选择自学
  • public Map kaoYanAllStation() { Map map = new HashMap<>(); ...

    首先 根据代码中的注释可以看出 该方法主要是获取各种气象数据 对其进行计算和比较 然后将结果存储在一个 Map 对象中返回 为了优化这段代码 可以考虑以下几个方面 减少重复代码 在代码中可以看到 获取历年同期降水和温度数据的代码几乎一模一样
  • LVS常用模式(DR、NAT、TUN)以及ldirector和keepalived

    1 LVS简单介绍 1 lvs定义LVS是Linux Virtual Server的简写 意即Linux虚拟服务器 是一个虚拟的服务器集群系统 LVS集群采用IP负载均衡技术和基于内容请求分发技术 调度器具有很好的吞吐率 将请求均衡地转移到
  • Java学习教程,Java从入门到精通,全套Java视频教程+笔记+配套工具

    目录 一 大纲 一 Java基础 二 计算机基础 三 工具的使用 四 数据库 五 web前端 六 JavaWeb 七 框架 八 互联网分布式技术 发现身边很多自学java却放弃的 真的挺可惜的 白白浪费了几个月宝贵的时间 且放弃一次 就会有
  • 第二十二章 Spring AOP⾥⾯的代理知识

    1 静态代理和动态代理 什么是代理 为某 个对象创建 个代理对象 程序不直接 原本的对象 是由创建的代理对象来控制对原对象 通过代理类这中间 层 能有效控制对委托类对象的直接访问 也可以很好地隐藏和保护委托类对象 同时也为实施不同控制策略预
  • 05-网络的四层协议和七层协议

    TCP IP网络分层模型 TCP IP的设计创造性的提出了分层的概念 把复杂的网络通信划分出多个层次 再为每一个层次分配不同的职责 层次内只专心做好自己的事情 用分而治之的思想把一个大麻烦拆分成了数个小麻烦 从而解决了网络的难题 TCP I
  • JAVA中的for循环使用方法

    一 循环结构 1 概念 在学习Java里的循环之前 我们先来了解一下到底什么是循环 以及循环的作用 我们先来看下面这张图 大家想一下 我们在400米的跑道上参加万米长跑 正常情况下要跑25圈 这25圈每一圈的跑步过程其实都是一样的 相当于是
  • springboot过滤器和拦截器

    一 过滤器和拦截器的区别 1 过滤器和拦截器触发时机不一样 过滤器是在请求进入容器后 但请求进入servlet之前进行预处理的 请求结束返回也是 是在servlet处理完后 返回给前端之前 2 拦截器可以获取IOC容器中的各个bean 而过
  • Volatility3内存取证工具使用详解

    Volatility 介绍 Volatility是一款开源的内存取证分析工具 是一款开源内存取证框架 能够对导出的内存镜像进行分析 通过获取内核数据结构 使用插件获取内存的详细情况以及系统的运行状态 支持Windows Linux MaC
  • org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder 找不到依赖包

    org springframework boot autoconfigure jdbc DataSourceBuilder 找不到依赖包 org springframework boot autoconfigure jdbc DataSou
  • PowerOJ2546: fork【C++ STL __gnu_cxx::rope】

    题目链接 我们可以这样定义一个可持久化数组 rope
  • MIPI TX控制器的设计

    MIPI接口在移动设备中被广泛应用 主要用于传输图像传感器 液晶显示器等外设的数据 以MIPI DPHY v1 2为例 它包含一个CLK lane和若干个DATA lane 可配置 每个lane的最高速率可达到2 5Gbps 对比SerDe
  • 向win7旗舰版U盘启动盘 添加usb3.0driver

    以前的主板usb采用的是ehci controller 仅支持usb2 0 而现在的主板一般采用xhci controller 同时支持usb2 0和usb3 0 win7的镜像安装包里面的驱动并没有xhci的驱动 所以在如今的很多新平台的
  • 怎么样对阿里云ECS主机进行绑定域名

    首先我有个阿里的 域名 虚拟云主机 搭建了一个wordpress 的网站 地址为 www liuxun name wordpress liuxun name wordpress 现在我想把一个阿里云的ECS主机 里面装了tomcat 希望以
  • GET请求里的body问题

    故事还得从一个bug说起 今天有人问我 为什么发到后端的请求400了 我说肯定是参数不对 你去检查检查GET POST之类的方法写没写对 要么就是字段没对上 无非是这几个问题 然后他说检查过了 没问题啊 我不太相信 但是看了看前端发送的请求