get请求可以传body吗_都9102年了,GET和POST的区别掌握了没有?

1 前言

最近看了一些同学的面经,发现无论什么技术岗位,还是会问到 get 和 post 的区别,而搜索出来的答案并不能让我们装得一手好逼,那就让我们从 HTTP 报文的角度来撸一波,从而搞明白他们的区别。

2 标准答案

在开撸之前吗,让我们先看一下标准答案长什么样子 w3school: GET 对比 POST。标准答案很美好,但是在面试的时候把下面的表格甩面试官一脸,估计会装逼不成反被*。

分类GETPOST后退按钮/刷新无害数据会被重新提交(浏览器应该告知用户数据会被重新提交)。书签可收藏为书签不可收藏为书签缓存能被缓存不能缓存编码类型application/x-www-form-urlencodedapplication/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多重编码。历史参数保留在浏览器历史中。参数不会保存在浏览器历史中。对数据长度的限制是的。当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。无限制。对数据类型的限制只允许 ASCII 字符。没有限制。也允许二进制数据。安全性与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分。在发送密码或其他敏感信息时绝不要使用 GET !POST 比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中。可见性数据在 URL 中对所有人都是可见的。数据不会显示在 URL 中。

注意,并不是说标准答案有误,上述区别在大部分浏览器上是存在的,因为这些浏览器实现了 HTTP 标准。但是,前面列举的只是浏览器实现上的区别,而不是 get 和 post 的本质区别。

3 GET 和 POST 报文上的区别

先下结论,GET 和 POST 方法没有实质区别,只是报文格式不同。

GET 和 POST 只是 HTTP 协议中两种请求方式,而 HTTP 协议是基于 TCP/IP 的应用层协议,无论 GET 还是 POST,用的都是同一个传输层协议,所以在传输上,没有区别。

报文格式上,不带参数时,最大区别就是第一行方法名不同

POST方法请求报文第一行是这样的 POST /uri HTTP/1.1

GET方法请求报文第一行是这样的 GET /uri HTTP/1.1

是的,不带参数时他们的区别就仅仅是报文的前几个字符不同而已

带参数时报文的区别呢? 在约定中,GET 方法的参数应该放在 url 中,POST 方法参数应该放在 body 中

举个例子,如果参数是 name=chengqm, age=22。

GET 方法简约版报文是这样的

GET /index.php?name=qiming.c&age=22 HTTP/1.1Host: localhost

POST 方法简约版报文是这样的

POST /index.php HTTP/1.1Host: localhostContent-Type: application/x-www-form-urlencodedname=qiming.c&age=22

现在我们知道了两种方法本质上是 TCP 连接,没有差别,也就是说,如果我不按规范来也是可以的。我们可以在 URL 上写参数,然后方法使用 POST;也可以在 Body 写参数,然后方法使用 GET。当然,这需要服务端支持。

4. 常见问题

GET 方法参数写法是固定的吗?

在约定中,我们的参数是写在 ? 后面,用 & 分割。

我们知道,解析报文的过程是通过获取 TCP 数据,用正则等工具从数据中获取 Header 和 Body,从而提取参数。

也就是说,我们可以自己约定参数的写法,只要服务端能够解释出来就行,一种比较流行的写法是 http://www.example.com/user/name/chengqm/age/22。

POST 方法比 GET 方法安全?

按照网上大部分文章的解释,POST 比 GET 安全,因为数据在地址栏上不可见。

然而,从传输的角度来说,他们都是不安全的,因为 HTTP 在网络上是明文传输的,只要在网络节点上捉包,就能完整地获取数据报文。

要想安全传输,就只有加密,也就是 HTTPS。

GET 方法的长度限制是怎么回事?

在网上看到很多关于两者区别的文章都有这一条,提到浏览器地址栏输入的参数是有限的。

首先说明一点,HTTP 协议没有 Body 和 URL 的长度限制,对 URL 限制的大多是浏览器和服务器的原因。

浏览器原因就不说了,服务器是因为处理长 URL 要消耗比较多的资源,为了性能和安全(防止恶意构造长 URL 来攻击)考虑,会给 URL 长度加限制。

POST 方法会产生两个TCP数据包?

有些文章中提到,post 会将 header 和 body 分开发送,先发送 header,服务端返回 100 状态码再发送 body。

HTTP 协议中没有明确说明 POST 会产生两个 TCP 数据包,而且实际测试(Chrome)发现,header 和 body 不会分开发送。

所以,header 和 body 分开发送是部分浏览器或框架的请求方法,不属于 post 必然行为。

5 talk is cheap show me the code

如果对 get 和 post 报文区别有疑惑,直接起一个 Socket 服务端,然后封装简单的 HTTP 处理方法,直接观察和处理 HTTP 报文,就能一目了然

#!/usr/bin/env python# -*- coding: utf-8 -*-import socketHOST, PORT = '', 23333def server_run(): listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) listen_socket.bind((HOST, PORT)) listen_socket.listen(1) print('Serving HTTP on port %s ...' % PORT) while True: # 接受连接 client_connection, client_address = listen_socket.accept() handle_request(client_connection)def handle_request(client_connection): # 获取请求报文 request = '' while True: recv_data = client_connection.recv(2400) recv_data = recv_data.decode() request += recv_data if len(recv_data) < 2400: break # 解析首行 first_line_array = request.split('')[0].split(' ') # 分离 header 和 body space_line_index = request.index('') header = request[0: space_line_index] body = request[space_line_index + 4:] # 打印请求报文 print(request) # 返回报文 http_response = b"""HTTP/1.1 200 OK Hello, World!

Hello, World!

""" client_connection.sendall(http_response) client_connection.close()if __name__ == '__main__': server_run()

上面代码就是简单的打印请求报文然后返回 HelloWorld 的 html 页面,我们运行起来

[root@chengqm shell]# python httpserver.py Serving HTTP on port 23333 ...

然后从浏览器中请求看看

c312ecc5f78090a97463685d71dfdbb3.png

打印出来的报文

32e798747bf0ce694c45da431513f485.png

然后就可以手动证明上述说法,比如说要测试 header 和 body 是否分开传输,由于代码没有返回 100 状态码,如果我们 post 请求成功就说明是一起传输的(Chrome/postman)。

6ab46982e3d7707b26d8c7b6b5dadd53.png

又比如 w3school 里面说 URL 的最大长度是 2048 个字符,那我们在代码里面加上一句计算 uri 长度的代码

...# 解析首行first_line_array = request.split('')[0].split(' ')print('uri长度: %s' % len(first_line_array[1]))...

我们用 postman 直接发送超过 2048 个字符的请求看看

d240de82790b733d2ecc185d957bcf3c.png

然后我们可以得出结论,url 长度限制是某些浏览器和服务器的限制,和 HTTP 协议没有关系。

到此,我们可以愉快地装逼了 :)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

玩转 Rockchip 的开发板,这些信息你要知道

RK 的处理器Rockchip 在江湖中简称 RK&#xff0c;是一家总部坐落于福建福州的 SOC 设计公司。RK 基于 Arm cortex-A 内核设计的一系列 SOC &#xff0c;宛如苍穹中一颗颗明星&#xff0c;在国内外的产业界和极客手中闪闪发光&#xff0c;其受欢迎程度超过了很多人的想象。登录…

htmlcss实例小项目_小程序websocket心跳库——websocket-heartbeat-miniprogram

前言在16年的时候因为项目接触到websocket&#xff0c;而后对心跳重连做了一次总结&#xff0c;写了篇博客&#xff0c;而后18年对之前github上的demo代码进行了再次开发和开源&#xff0c;最终封装成库。如下&#xff1a;博客&#xff1a;https://www.cnblogs.com/1wen/p/5808…

C语言,画吃豆人剖析

接上一篇文章&#xff0c;很多人还是搞不清楚ptr1[-1]是怎么回事&#xff0c;可以看看这篇文章&#xff0c;看完的同学还是多转发的&#xff0c;让更多的人看到。一道90%都会做错的指针题偶然的一次机会在知乎上看到这个代码&#xff0c;里面涉及的C语言点我觉得很酷&#xff0…

mit数据集_DriveSeg:动态驾驶场景分割数据集

【导读】麻省理工学院和丰田发布DriveSeg数据集以加速自动驾驶研究&#xff0c;DriveSeg包含许多常见道路对象的精确像素级表示&#xff0c;并通过连续视频驾驶场景的镜头。我们如何训练自动驾驶模型&#xff0c;以加深对周围世界的认识&#xff1f;计算机能否从过去的经验中学…

没有长夜痛哭的人,不足以谈人生

早上骑电动车上班了&#xff0c;之前已经连续开车上班有一段时间&#xff0c;每天出公司交停车费心都在滴血&#xff0c;活了30年了&#xff0c;想不到我还是这样穷&#xff0c;我总是觉得明天是最好的一天&#xff0c;即使过得不是十分如意&#xff0c;但是我遇到困难的时候总…

android ne调试工具,Android调试工具adb的正确使用方式

引言&#xff1a;通常在使用Eclipse进行Android应用开发的时候&#xff0c;我们可以使用Eclipse自带的工具来完成调试和查看输出日志的操作&#xff0c;但是假如在当前电脑并没有配置适用于Android开发的Eclipse版本的情况下&#xff0c;想要查看Android设备运行应用或者游戏时…

为什么使用模板

C模板编程是泛型编程的实现方式&#xff0c;因为C中的类型都是强类型。所以导致每个变量都有一种相应的类型。这样就会出现一个弊端&#xff0c;就是相同一个算法针对不同类型的參数&#xff0c;就要实现多个版本号&#xff0c;这样岂不是非常麻烦。那么&#xff0c;C中是否会有…

eltable刷新整个表格方法_利用SSAS实现PBI报表增量刷新

欢迎访问我的博客网站阅读最新BI文章对于经常处理大量数据且其Power BI报表不需要每次都刷新整个数据集的用户而言&#xff0c;增量刷新一直都是个问题&#xff0c;特别是对于那些没有条件使用Premium空间的用户以及在本地报表服务器发布报表的用户。一个稳定可靠的方法是利用S…

我和Git的第一次

我第一次接触Git应该是在2010年&#xff0c;我那年买了第一块Linux开发板&#xff0c;是友善之臂的mini2440&#xff0c;就是这个开发板打开了我Linux的大门&#xff0c;价格是499&#xff0c;我两个月的生活费。如果说到了Linux&#xff0c;不说Git就有点说不过去了&#xff0…

创建线程的方式_创建线程有几种不同的方式?

方式可以用来创建线程1&#xff09;继承Thread类2&#xff09;实现Runnable接口3&#xff09;应用程序可以适用Executor框架来创建线程池实现了Runnable接口这种方式更受欢迎&#xff0c;因为这不需要继承Thread类。在应用设计中已经继承了别的对象的情况下&#xff0c;这需要多…

内存屏障,先看这篇文章

刚看到这个词的时候&#xff0c;我以为是白内障&#xff0c;然后查了很多资料&#xff0c;才理解内存屏障是干嘛的&#xff0c;我就不像很多其他文章说得那么多了&#xff0c;我希望我说得简单一些&#xff0c;让大家看了我的文章都知道这个是怎么回事。说到内存屏障&#xff0…

SpringMVC原理及非注解配置详解

如需转发请标明出处&#xff1a;http://www.cnblogs.com/gudu1/p/7222556.html 1. Spring介绍 Spring MVC是Spring提供的一个强大而灵活的web框架。借助于注解&#xff0c;Spring MVC提供了几乎是POJO的开发模式&#xff0c;使得控制器的开发和测试更加简单。 这些控制器一般不…

ftp 追加远程文件_远程办公彻底火了,高效办公,拒绝卡顿,远程利器你选对了么?...

远程办公的同时肯定会应用到公司的内部系统了&#xff0c;比如OA、ERP等系统&#xff0c;当然为了提高远程办公人员的工作效率&#xff0c;实现资源共享最大化&#xff0c;企业FTP服务的应用也是必不可少。无论是员工出差还是修改&#xff0c;一旦涉及文件的应用&#xff0c;通…

android jxl.jar 使用,使用jxl.jar在Android中操作Excel表格——重中之重——对隐藏表的处理...

曾简单了解过C#&#xff0c;将Excel(数据库表)表中的数据导入到C#中&#xff0c;使用C#制作的图形化界面进行对Excel表中数据进行操作。今天想试试&#xff0c;在Android中导入Excel表格进行操作。在网上查阅资料&#xff0c;找到了jxl.jar包。jxl.jarjxl.jar是通过java操作exc…

自定义协议的这些典型例子你会了吗?

上次分享的《分享一个很酷的上位机软件》中&#xff0c;有如下协议&#xff1a;有位读者朋友问数据为什么要按这样的格式来发。其实这是个自定义协议&#xff0c;这是上位机开发者定义的一个数据交互协议。我们下位机往伏特加上位机发送数据需要遵循这样的协议数据&#xff0c;…

java 原子类_小学妹教你并发编程的三大特性:原子性、可见性、有序性

在并发编程中有三个非常重要的特性&#xff1a;原子性、有序性,、可见性&#xff0c;学妹发现你对它们不是很了解&#xff0c;她很着急&#xff0c;因为理解这三个特性对于能够正确地开发高并发程序有很大的帮助&#xff0c;接下来的面试中也极有可能被问到&#xff0c;小学妹就…

关于a标签不能调用js方法的小细节,你注意到了么?

在我们做后台删除的时候&#xff0c;当点击删除标签时&#xff0c;你希望弹出一个友好的提示框&#xff01;比如这样&#xff1a; 那代码应该怎样写呢&#xff1f;向下面这样&#xff1f; <!DOCTYPE html> <html lang"en"> <head><meta charset…

4岁小女孩给Linux内核贡献提交

今天在reddit上看到一个有趣的讨论&#xff0c;一个4岁的小女孩给Linux提交了一个补丁&#xff0c;并且这个补丁合并到了代码中。链接如下&#xff1a;https://www.reddit.com/r/linux/comments/2pqqla/kernel_commit_4_year_old_girl_fixes_formatting_to/cmzfvpl/我们看看她修…

php文件上传后没有打开权限_记墨者靶机文件上传(二)

“ 声明&#xff1a;该公众号大部分文章来自日常学习笔记&#xff0c;若是转载会先得到原作者授权或其他公众号白名单&#xff0c;并附上链接。剑者&#xff0c;心之刃也。既可为杀&#xff0c;亦可为护。杀与护&#xff0c;不过一念之间&#xff01;请勿利用文章内的相关技术从…

你还会写这段C51程序吗?

经典题目解析定时器T1采用计数模式&#xff0c;方式1中断&#xff0c;计数输入引脚 P3.5外接开关按钮作为计数信号输入&#xff0c;P1口控制8个LED小灯&#xff0c;初始状态所有小灯全亮&#xff0c;按3次按钮开关产生计数中断时&#xff0c;高3位和低5位交替闪烁3次&#xff0…