[/
    Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

    Official repository: https://github.com/boostorg/beast
]

[section 消息容器]

Beast 提供单个类模板 __message__ 及若干别名，用于表示 HTTP/1 和 HTTP/2 消息：

[table 消息
[[名称][描述]]
[[__消息__
][
    ```
/// HTTP 消息类
template<
bool isRequest, // 若为请求则为 true，若为响应则为 false
class Body, // 用于控制消息体的容器及算法
class Fields = fields> // 用于存储字段的容器类型
class message;
    ```
]]
[[
    [link beast.ref.boost__beast__http__request `request`]
][
    ```
/// 典型的 HTTP 请求
template<class Body, class Fields = fields>
using request = message<true, Body, Fields>;
    ```
]]
[[
    [link beast.ref.boost__beast__http__response `response`]
][
    ```
/// 典型的 HTTP 响应
template<class Body, class Fields = fields>
using response = message<false, Body, Fields>;
    ```
]]
]

该容器提供值语义，支持移动和拷贝操作（前提是 __Body__ 和 __Fields__ 支持这些操作）。用户定义的模板函数参数可以接受任意消息，也可通过偏特化仅接受请求或响应。默认的 __fields__ 是一个关联容器，使用标准分配器，支持字段的修改与查询。根据 __rfc7230__，字段名称比较时不区分大小写。用户也可以自定义字段类型。`Body` 类型决定消息体的容器类型，以及用于在容器与缓冲区之间传输数据的算法。该库提供一组常用的消息体类型。与字段类似，用户也可以自定义消息体类型。

有时只需处理头部信息。Beast 提供单个类模板 __header__ 及若干别名，用于表示 HTTP/1 和 HTTP/2 头部：

[table 头部
[[名称][描述]]
[[__头部__
][
    ```
/// HTTP 头部
template<
bool isRequest, // 若为请求则为 true，若为响应则为 false
class Fields = fields> // 用于存储字段的容器类型
class header;
    ```
]]
[[
    [link beast.ref.boost__beast__http__request_header `request_header`]
][
    ```
/// 典型的 HTTP 请求头部
template<class Fields>
using request_header = header<true, Fields>;
    ```
]]
[[
    [link beast.ref.boost__beast__http__response_header `response_header`]
][
    ```
/// 典型的 HTTP 响应头部
template<class Fields>
using response_header = header<false, Fields>;
    ```
]]
]

请求和响应共享版本号、字段及消息体，但各自拥有一些特有的成员。该设计通过将 `header` 类声明为 `isRequest` 的偏特化来实现。__message__ 派生自 __header__，因此消息可作为参数传递给接受相应类型头部参数的函数。此外，`header` 公开继承自 `Fields`，因此消息也继承了 `Fields` 的所有成员函数。下图展示 `header` 与 `message` 的继承关系，以及每个偏特化中部分显著成员的差异：

[$beast/images/message.png [width 730px] [height 459px]]

[heading:body 消息体类型]

Beast 定义 __Body__ 概念，该概念决定 [link beast.ref.boost__beast__http__message.body `message::body`] 成员的类型，同时还可包含用于传入和传出缓冲区的算法。这些算法在解析和序列化过程中使用。用户可以定义满足要求的自定义消息体类型，也可以直接使用该库提供的现有类型：

[table
[[Name][Description]]
[[
    [link beast.ref.boost__beast__http__buffer_body `buffer_body`]
][该消息体类型的 [link beast.ref.boost__beast__http__buffer_body__value_type `value_type`] 包含一个原始指针及其长度，指向调用方提供的缓冲区。该类型支持对来自外部来源的消息体数据进行序列化，并使用固定大小的缓冲区进行消息体内容的增量解析。
]]
[[
    [link beast.ref.boost__beast__http__dynamic_body `dynamic_body`]

    [link beast.ref.boost__beast__http__basic_dynamic_body `basic_dynamic_body`]
][该消息体类型的 `value_type` 为一个 __DynamicBuffer__。其插入操作的复杂度取决于底层动态缓冲区的选择。带有该消息体类型的消息支持序列化和解析操作。
]]
[[
    [link beast.ref.boost__beast__http__empty_body `empty_body`]
][该消息体类型为一个特殊的空消息体，其 `value_type` 为空，表示消息不包含消息体。带有该消息体类型的消息支持序列化和解析操作；但在解析过程中如果接收到消息体数据，则会生成一个特定的错误。
]]
[[
    [link beast.ref.boost__beast__http__file_body `file_body`]

    [link beast.ref.boost__beast__http__basic_file_body `basic_file_body`]
][该消息体类型通过一个已打开的文件来表示，可用于读取或写入。带有该消息体类型的消息支持序列化和解析操作。HTTP 算法会利用这个已打开的文件执行读写操作，从而支持流式传输及增量式数据收发。
]]
[[
    [link beast.ref.boost__beast__http__span_body `span_body`]
][该消息体类型的 `value_type` 为 [@boost:/libs/core/doc/html/core/span.html `span`]，这是一个指向单个线性字节缓冲区的非拥有引用。带有该消息体类型的消息可进行序列化和解析。
]]
[[
    [link beast.ref.boost__beast__http__string_body `string_body`]

    [link beast.ref.boost__beast__http__basic_string_body `basic_string_body`]
][该消息体类型的 `value_type` 为 `std::basic_string` 或 `std::string`。插入操作的均摊复杂度为常数时间，容量以几何级数增长。带有该消息体类型的消息支持序列化和解析操作。此类型即为示例中使用的消息体类型。
]]
[[
    [link beast.ref.boost__beast__http__vector_body `vector_body`]
][该消息体类型的 `value_type` 为 `std::vector`。插入操作的均摊复杂度为常数时间，容量以几何级数增长。带有该消息体类型的消息支持序列化和解析操作。
]]
]

[heading 用法]

以下示例展示如何创建并填充请求和响应对象。这里构造一个带有空消息体的 [@https://tools.ietf.org/html/rfc7231#section-4.3.1 HTTP GET] 请求：

[table 创建请求
[[声明] [序列化结果]]
[[
    [http_snippet_2]
][
```
    GET /index.htm HTTP/1.1\r\n
    Accept: text/html\r\n
    User-Agent: Beast\r\n
    \r\n
```
]]
]

以下代码创建一个带有成功状态码的 HTTP 响应。该消息包含一个非空的消息体。prepare_payload 函数会根据 body 成员的内容和类型自动设置 Content-Length 或 Transfer-Encoding 字段。该函数可调用也可不调用；这些字段也可手动显式设置。

[table 创建响应
[[声明] [序列化结果]]
[[
    [http_snippet_3]
][
```
    HTTP/1.1 200 OK\r\n
    Server: Beast\r\n
    Content-Length: 13\r\n
    \r\n
    Hello, world!
```
]]
]

当序列化消息时，实现会根据状态码自动填充已废弃的 [@https://tools.ietf.org/html/rfc7230#section-3.1.2 原因短语]。也可通过调用 [link beast.ref.boost__beast__http__header.reason.overload2 `header::reason`] 直接设置该字段。

[endsect]
