> For the complete documentation index, see [llms.txt](https://meetbill.gitbook.io/butterfly-project-doc/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://meetbill.gitbook.io/butterfly-project-doc/project-framework/how/http.md).

# HTTP 协议基础

## HTTP 协议基础

* 一次请求
* 报文

### 一次请求

```
#curl -v -d '{"str_info":"meetbill"}' "http://127.0.0.1:8585/x/hello"
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 8585 (#0)
> POST /x/hello HTTP/1.1
> Host: 127.0.0.1:8585
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Length: 23
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 23 out of 23 bytes
< HTTP/1.1 200 OK
< meetbill: 1.0.1
< Content-Length: 38
< butterfly: 1.0.5
< x-reqid: EDD1FFCB01842079
< x-cost: 0.008146
< Date: Sun, 20 Oct 2019 12:21:05 GMT
< Server: XXXXXXXXX
<
* Connection #0 to host 127.0.0.1 left intact
{"stat": "OK", "str_info": "meetbill"}
```

### 报文

http 是典型的报头 + 报体的这个一个约定格式。

* 通过 \r\n\r\n 来区分报头和报体
* 报头通过 \r\n 来区分不同的信息

> 看个示例

```
POST /x/hello HTTP/1.1\r\n
Host: 127.0.0.1:8585\r\n
User-Agent: curl/7.54.0\r\n
Accept: */*\r\n
Content-Length: 23\r\n
Content-Type: application/x-www-form-urlencoded\r\n
\r\n
{"str_info":"meetbill"}
```

> CRLF

```
CRLF 是 Carriage-Return Line-Feed 的缩写，意思是回车换行，就是回车 (CR, ASCII 13, \r) 换行 (LF, ASCII 10, \n)
```

> 理解 TCP 流的概念及粘包的现象

```
HTTP 是基于 TCP 的上层应用协议，tcp 是数据流，这里有两个要点：

(1) 数据没有边界
你可以理解为水在一个水管里的流动，我们不知道哪段数据是一个我们需要的完整数据

(2) 收发有缓冲区
比如：当水从一端流到了另一端，我们在收数据的时候，不可能每来一滴水就处理一次，这个缓冲区就相当于有了一个水桶，再接了一定的水之后内核再给数据交到用户空间，这样可以大大提升性能。

那这里就有一个问题：由于这个特性，内核无法知道哪部分数据是你想要的，所以应用层拿到数据可能是完整数据，也可能是不完整或者一部分完整、一部分不完整（粘包），那么怎样能得到想要的数据呢？

http/1.1 之前，每次请求响应都使用新的 tcp 连接，所以不需要考虑数据边界问题。
http/1.1 支持 keep-alive，多个 message 可以使用同一个 tcp 连接，所以要有确定边界的机制。或者无视客户端的 Connection: keep-alive 头，一律返回 Connection: close，就不用操心这个问题了。
```
