关于http协议GET和POST方法的区别我们可以从各处得到比较一致的答案,今天我们来填一个面试中可能碰到的一个坑。
当面试官问你“你觉得GET和POST有什么区别"时,我们可能会想到以下几点(来源于网络):
- GET在浏览器回退时是无害的,而POST会再次提交请求。
- GET产生的URL地址可以被Bookmark,而POST不可以。
- GET请求会被浏览器主动cache,而POST不会,除非手动设置。
- GET请求只能进行url编码,而POST支持多种编码方式。
- GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
- 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
- GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
- GET参数通过URL传递,POST放在Request body中。
- GET请求在URL中传送的参数是有长度限制的,而POST么有。
以上答案除了最后2条基本没什么问题,我们现在测试一下到底什么情况。
在HTTP协议中并没有明确论述不同的请求方法使用的传送数据方式(url,body)不同,所以我们假设没有这种区别。
我们实现一个的socket server 端程序进行测试
package main import ( "fmt" "log" "net" ) func main() { l, err := net.Listen("tcp", ":8080") if err != nil { log.Fatalln("err:", err) } defer l.Close() for { c, err := l.Accept() if err != nil { log.Fatalln("err:", err) } go process(c) } } func process(c net.Conn) { defer func() { c.Close() if err := recover(); err != nil { log.Println("process error:", err) } }() rH := `HTTP/1.1 200 OK Content-Type:"application/json"` rSegmentation := " " rB := `{"data":"success"}` resp := rH + rSegmentation + rB bs := make([]byte, 1024) // 读请求 n, _ := c.Read(bs) fmt.Println(string(bs[:n])) // 响应 c.Write([]byte(resp)) }
GET方法通过url传递数据如下
server接收到的http请求
GET方法通过body传递数据如下
server接收到的请求
POST方法通过url传递数据
server接收到的请求
POST方法通过body传递数据
server接收到的请求
上述四种测试case均成功,所以“GET参数通过URL传递,POST放在Request body中”和“GET请求在URL中传送的参数是有长度限制的,而POST么有”是错误的。具体来说:
- 无论POST还是GET方法,传递数据(参数)既可通过URL也可以通过body
- POST或者GET方法如果通过body传递数据(参数)是没有长度限制的
- POST或者GET方法通过URL传递数据理论上也没有长度限制(因为url存在于http协议的header部分,而http header并没有长度限制)
- 通常所说的参数数据限制是指浏览器或者werbserver会的一种设定,假如自己实现client和server完全能做到不限制长度
所以从协议角度来看GET和POST本质上并没有区别.