昨天上班的时候后端有一个delete请求,要求我把参数放在urlquery string上面。于是我说其实可以放在请求的实体中,但是后端说deleteget是没有请求实体的。这和我的记忆不太一样。那么到底deletepost请求能有实体吗?

先看网上的资料

先通过简单的搜索在stack overflow找到一个类似的问题, Is an entity body allowed for an HTTP DELETE request?。回答中说到并没有禁止和不推荐在getdelete方法中使用实体。意思就是说其实是可以使用的。那么再看回答中给出的规范的资料,确实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请求,getdelete请求不能携带实体。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐