昨天上班的时候后端有一个delete
请求,要求我把参数放在url
的query string
上面。于是我说其实可以放在请求的实体中,但是后端说delete
和get
是没有请求实体的。这和我的记忆不太一样。那么到底delete
和post
请求能有实体吗?
先通过简单的搜索在stack overflow找到一个类似的问题, Is an entity body allowed for an HTTP DELETE request?。回答中说到并没有禁止和不推荐在get
和delete
方法中使用实体。意思就是说其实是可以使用的。那么再看回答中给出的规范的资料,确实http规范中并没有说明有任何方法不能使用 实体。
但是有时候现实生活往往和规范不一致。所以我们还要试验一下,首先是我们先用node
搭建一个服务器,打印收到的实体:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
const http = require('http'); http.createServer((req, res) => { const { method, url } = req; console.log(`METHOD: ${method}`); console.log(`URL:${url}`); const body = []; req .on('data', (chunk) => { body.push(chunk) }) .on('end', () => { let bodyString = Buffer.concat(body).toString(); console.log(`BODY: ${body}`) res.end(bodyString || 'body is empty'); }); }).listen(3000);在浏览器中使用ajax测试
get请求
在浏览器中打开localhost:300
页面,并且在控制台执行以下代码:
1 2 3 4 5
(function() { const ajax = new XMLHttpRequest(); ajax.open('get', 'http://localhost:3000?qs=qs'); ajax.send('name=bob'); })()
服务器打印:
1 2 3
METHOD: GET URL:/?qs=qs BODY:
没有接收到body
delete请求
delete
请求: 在浏览器中打开localhost:300
页面,并且在控制台执行以下代码:
1 2 3 4 5
(function() { const ajax = new XMLHttpRequest(); ajax.open('delete', 'http://localhost:3000?qs=qs'); ajax.send('name=bob'); })()
服务器打印:
1 2 3
METHOD: DELETE URL:/?qs=qs BODY: name=bob
接收到body
使用curl命令测试get请求
命令行中执行下面的命令:
1
curl -X GET -d 'name=bob' localhost:3000
服务器打印:
1 2 3
METHOD: GET URL:/ BODY: name=bob
接收到body
delete请求
1
curl -X DELETE -d 'name=bob' localhost:3000
服务器打印:
1 2 3
METHOD: DELETE URL:/ BODY: name=bob
接收到body
发现curl
命令的body都是可以正常发送,但是浏览器中的ajax却不行这是为什么呢?查看XMLHttpRequest
规范发现:
The send(body) method must run these steps:
1. If state is not opened, then throw an "InvalidStateError" DOMException.
2. If the send() flag is set, then throw an "InvalidStateError" DOMException.
3. If the request method is GET or HEAD, set body to null.
4. If body is not null, then:
5. ....
原来XMLHttpRequest
规范定义method时get或者head的时候,XMLHttpRequest会忽略body。所以会产生前面实验的现象。
那么这些请求到底有什么不一样呢
其实从http报文的角度看,他们完全都是一样的。没有任何区别,大家能发送的信息都是一样的。你能做的我也能做,不一样的在于method
所代表的这个请求的语义。
结论
最后总结一下,在http规范任何方法都能发送请求实体。他们报文时没有任何区别的,但是在浏览器中,因为XMLHttpRequest
规范的限制,浏览器中ajax发送的http请求,get
,delete
请求不能携带实体。