一文告知HTTP GET是否可以有请求体

2023-10-10 08:12

本文主要是介绍一文告知HTTP GET是否可以有请求体,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

HTTP GET是否可以有请求体

先说结论:
HTTP协议没有规定GET请求不能携带请求体,但是部分浏览器会不支持,因此不建议GET请求携带请求体。

  • HTTP 协议没有为 GET 请求的 body 赋予语义,也就是即不要求也不禁止 GET 请求带 body。
  • 大多数 HTTP 实现从技术上都支持 HTTP GET 请求带 body,少数实现会禁止(google-chrome 浏览器、node-fetch),少数实现会不建议(Fiddler)。

1 HTTP协议对GET请求包含BODY的规定

1.1 RC1945

RFC 1945 发布于 1996 年,描述了 HTTP/1.0 。

其中和 body 有关的第 7 节提到了一下内容:

Full-Request and Full-Response messages may transfer an entity within some requests and responses. An entity consists of Entity-Header fields and (usually) an Entity-Body.
译:Full-Request 和 Full-Response 消息可以在某些请求和响应中传输实体。实体包括实体首部字段,并且通常包括一个实体 body。

说明 HTTP/1.0 会通过请求或响应的 body 传输实体,并且没有限定哪些请求方法不能传输实体。也就是说 GET 也可以有 body。

另外其 8.1 节关于 GET 和 POST 方法有如下描述:

The GET method means retrieve whatever information (in the form of an entity) is identified by the Request-URI.
译:GET 方法表示查询由 Request-URI 标识的任何信息(形式为实体)。
The POST method is used to request that the destination server accept the entity enclosed in the request …
译:POST 方法用于请求目标服务器接受包含在请求中的实体 …

说明 GET 方法的语义是请求实体,POST 方法的语义是提交实体,两者有明确的分工。

RFC 1945 这两处的内容可以提炼出两条信息:

  1. 请求或响应需要传输实体时才会有 body。
  2. GET 请求用于请求实体,而不是传输实体。
    根据这两条信息可以推出,GET 请求没有传输实体的语义,自然也不需要 body。但 RFC 1945 也没有明确规定 GET 请求不能传输实体、不能有 body。所以按 HTML 1.0 规范,GET 请求是可以有 body 的,只不过没有为其定义语义。

1.2 RFC 2068

RFC 2068 发布于 1997 年,描述了 HTTP/1.1。

RFC 2068 是对 RFC 1945 的更新,在 4.3 节有以下描述:

A message-body MAY be included in a request only when the request method allows an entity-body.
译:只有当请求方法允许使用实体 body 时,请求中才可以包含消息 body。

第 9 节是关于各个 HTTP 请求方法的描述,但只有第 9.8 节提到:

A TRACE request MUST NOT include an entity.
译:TRACE 请求必须不能包含实体。

另外,对 PUT、POST 的描述都默认有实体。但是对 GET 描述并没有提到请求中是否能包含实体 body。

也就是说 TRACE 不允许包含 body,PUT、POST 请求包含 body,但是 GET 没有明确说明,这种没说明的情况到底是允许还是不允许呢?

1.3 RFC 2616

RFC 2616 发布于 1999 年,是对 RFC 2068 的更新,还是描述的 HTTP/1.1。

其 4.3 节增加了如下描述:

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. 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.
译:如果本规范规定了某个请求方法不允许发送实体,则绝不能在请求中包含消息 body。服务器应该读取和转发任何请求的消息体(body);如果某个请求方法没有定义实体语义,那么在处理请求时应该忽略消息体(body)。

但第 9 节对于各个方法的描述中还是没有说 GET 请求是否能有 body。

1.4 RFC 7231

2004 年发布的 RFC 7230~7235 是对 RFC 2626 的修订。其中 RFC 7231 是 HTTP 的“核心”语义规范,终于在 4.3.1 节明确提到了 GET 请求的 body:

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)没有定义的语义;在 GET 请求上发送有效负载主体可能会导致某些现有实现拒绝该请求。

说明修订规范的人也知道有的 HTTP server 实现会拒绝带有 body 的 HTTP GET 请求。但是为什么规范迭代了这么多次都不规定每个请求方法是否能包含 body 呢?留下这么大的争议空间也是醉了。

2 现有实现对 GET 请求 body 的支持

请求库/工具是否支持GET带body
XMLHttpRequest不支持
Fetch不支持
Requests(Python最流行的HTTP请求库)支持
HTTPX(Python库)支持
axios(基于Promise的HTTPClient库)支持
superagent支持
node-fetch(Node.js的一个HTTP请求库)不支持
curl支持
Postman支持
Apifox支持
Fiddler支持,但是会用红色告警
nginx支持
FastAPI支持
  • Fildder发送GET请求红色警告⚠️图:

在这里插入图片描述

3 结论

🚀HTTP协议中没有明确规定GET请求是否能带body,市场上部分浏览器会不支持GET请求带body。

软件工程中有一条原则:不要依赖未定义的行为。HTTP 协议未定义 GET 请求的 body 语义,如果想用 GET 请求发送 body,得先为其定义语义,并确保上下游都能很好的支持。作为服务接口的提供方,不应该假设所有的调用方都能发出 GET 请求 body;作为调用方,不应该假设服务方能完美解析 GET 请求 body,但如果服务方提供了支持 GET 请求 body 的接口,可以放心使用,不用纠结。

软件工程中还有另一条原则,不记得原文了,翻译成中国的老话就是:严于律己,宽已待人。我们在写库、写框架、写工具时应该支持 GET 请求带 body;在封装接口时,尽量不要强制调用方用 GET body 提交数据,除非遇到用 GET body 才符合逻辑的特殊情况;在使用别人提供的库、框架、工具,或者调用协作方提供的接口时不应该强求对方支持 GET 请求 body。

参考文章:
https://zhuanlan.zhihu.com/p/456921996

这篇关于一文告知HTTP GET是否可以有请求体的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/179193

相关文章

一文详解SpringBoot中控制器的动态注册与卸载

《一文详解SpringBoot中控制器的动态注册与卸载》在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性,下面我们就来看看Sp... 目录项目结构1. 创建 Spring Boot 启动类2. 创建一个测试控制器3. 创建动态控制器注

一文详解Git中分支本地和远程删除的方法

《一文详解Git中分支本地和远程删除的方法》在使用Git进行版本控制的过程中,我们会创建多个分支来进行不同功能的开发,这就容易涉及到如何正确地删除本地分支和远程分支,下面我们就来看看相关的实现方法吧... 目录技术背景实现步骤删除本地分支删除远程www.chinasem.cn分支同步删除信息到其他机器示例步骤

springboot如何通过http动态操作xxl-job任务

《springboot如何通过http动态操作xxl-job任务》:本文主要介绍springboot如何通过http动态操作xxl-job任务的问题,具有很好的参考价值,希望对大家有所帮助,如有错... 目录springboot通过http动态操作xxl-job任务一、maven依赖二、配置文件三、xxl-

Python get()函数用法案例详解

《Pythonget()函数用法案例详解》在Python中,get()是字典(dict)类型的内置方法,用于安全地获取字典中指定键对应的值,它的核心作用是避免因访问不存在的键而引发KeyError错... 目录简介基本语法一、用法二、案例:安全访问未知键三、案例:配置参数默认值简介python是一种高级编

一文详解Java Stream的sorted自定义排序

《一文详解JavaStream的sorted自定义排序》Javastream中的sorted方法是用于对流中的元素进行排序的方法,它可以接受一个comparator参数,用于指定排序规则,sorte... 目录一、sorted 操作的基础原理二、自定义排序的实现方式1. Comparator 接口的 Lam

一文深入详解Python的secrets模块

《一文深入详解Python的secrets模块》在构建涉及用户身份认证、权限管理、加密通信等系统时,开发者最不能忽视的一个问题就是“安全性”,Python在3.6版本中引入了专门面向安全用途的secr... 目录引言一、背景与动机:为什么需要 secrets 模块?二、secrets 模块的核心功能1. 基

一文详解MySQL如何设置自动备份任务

《一文详解MySQL如何设置自动备份任务》设置自动备份任务可以确保你的数据库定期备份,防止数据丢失,下面我们就来详细介绍一下如何使用Bash脚本和Cron任务在Linux系统上设置MySQL数据库的自... 目录1. 编写备份脚本1.1 创建并编辑备份脚本1.2 给予脚本执行权限2. 设置 Cron 任务2

一文详解如何在idea中快速搭建一个Spring Boot项目

《一文详解如何在idea中快速搭建一个SpringBoot项目》IntelliJIDEA作为Java开发者的‌首选IDE‌,深度集成SpringBoot支持,可一键生成项目骨架、智能配置依赖,这篇文... 目录前言1、创建项目名称2、勾选需要的依赖3、在setting中检查maven4、编写数据源5、开启热

python判断文件是否存在常用的几种方式

《python判断文件是否存在常用的几种方式》在Python中我们在读写文件之前,首先要做的事情就是判断文件是否存在,否则很容易发生错误的情况,:本文主要介绍python判断文件是否存在常用的几种... 目录1. 使用 os.path.exists()2. 使用 os.path.isfile()3. 使用

Maven 配置中的 <mirror>绕过 HTTP 阻断机制的方法

《Maven配置中的<mirror>绕过HTTP阻断机制的方法》:本文主要介绍Maven配置中的<mirror>绕过HTTP阻断机制的方法,本文给大家分享问题原因及解决方案,感兴趣的朋友一... 目录一、问题场景:升级 Maven 后构建失败二、解决方案:通过 <mirror> 配置覆盖默认行为1. 配置示