[/
    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 FAQ]

为确立合理预期并避免大量重复的评审意见，本说明针对 Beast 及其他经过正式评审的 HTTP 库最常见的疑问和评论进行解答。

[variablelist
[[
    "Beast requires too much user code to do anything!"
][
    It is not the intention of the library to provide turn-key
    solutions for specific HTTP or WebSocket use-cases.
    Instead, it is a sensible protocol layering on top of
    Boost.Asio which retains the Boost.Asio memory
    management style and asynchronous model. 
]]
[[“Beast 不提供 HTTP 服务器？”
][Beast 在示例目录中提供功能完备的 HTTP 服务器。该服务器支持 HTTP 和 WebSocket，可通过同步或异步方式使用共享端口或专用端口。此外，若存在 OpenSSL，该服务器支持在专用端口上建立加密的 TLS 连接。该服务器提供“多端口”模式，这是一种灵活的单端口模式，可在同一端口上同时支持加密与非加密连接，以及 HTTP 和 WebSocket。该服务器未纳入 Beast 的公共接口，因为相关功能超出该库的范畴。作者认为，试图扩大库的范围会降低其标准化的吸引力。
]]
[[“Beast 不提供 HTTP 客户端？”
][“我只想通过 HTTP 下载资源”，这是用户和评审人员经常提出的诉求。此类功能超出 Beast 的范畴。构建一个功能完备的 HTTP 客户端是一项艰巨的任务，其体量足以成为一个独立的库。其中存在诸多需要处理的事项，例如各类消息体编码、复杂的标头解析、Range 和 Cache-Control 等晦涩的标头语义、重定向、Expect: 100-continue、连接重试、域名解析、TLS 等。作者认为，Boost 首先需要一套用于在协议层面操作 HTTP 的通用名词和动词，而 Beast 正是提供该语言的库。
]]
[[“目前还不支持 HTTP/2！”
][许多评审人员认为，HTTP/2 支持是 HTTP 库的必备功能。作者认同 HTTP/2 的重要性，但也认为最合理的实现方式是不应让 HTTP/2 复用 HTTP/1.0 和 HTTP/1.1 相同的网络读写接口。

Beast 的 HTTP 消息模型在设计时已考虑到新协议，应在该语境下进行评估。未来存在增加 HTTP/2 支持的计划，但目前无需急于推进。用户当前即可使用 HTTP/1，不应为了等待未来的新协议而剥夺用户当前的功能使用权。作者认为，Beast 仅支持 HTTP/1 的实现已具备足够价值，缺乏 HTTP/2 不应成为阻碍其被接纳的理由。

Beast 的 HTTP 消息模型适用于 HTTP/2 并可被复用。IETF HTTP 工作组已将消息与 HTTP/1.x 兼容作为明确目标。解析器在解码压缩的 HTTP/2 标头后，可直接输出完整标头。流 ID 在逻辑上不属于消息本身，而是消息元数据，应通过带外方式进行通信（见下文）。HTTP/2 会话以传统的 HTTP/1.1 升级握手开始，其方式与 WebSocket 升级类似。HTTP/2 的实现可使用现有的 Beast.HTTP 原语来执行该握手。
]]
[[“这应该能配合 standalone-Asio 使用！”
][Beast 不仅依赖 Boost.Asio，还依赖 Boost 的其他组件。目前 standalone Asio 的版本领先于 Boost 中的版本。作者当前没有足够的资源来同时维护 Beast 对这两个 Asio 版本的兼容性。与非 Boost 库的兼容性不应作为接纳标准。Beast 的设计定位就是作为 Boost 的一部分，仅此而已。从宏观角度来看，作者的目标是推动该库走向标准化。实现这一目标的合理路径如下：

[ordered_list [ 被接纳为 Boost 库。][ 移植到 Boost.Asio 版本的 Networking-TS（这需等待 Boost 中的 Asio 版本更新）。][ 等待 Networking-TS 成为 C++ 的正式组成部分。][ 移植到标准库版本的 networking（gcc、clang、msvc）。][ 开发提议的语言特性（此步骤可与第 3、4 步并行推进）]]
]]
[[“你需要基准测试！”
][投入在 Beast 上的精力主要集中在接口设计上，而非性能。话虽如此，Beast 中最敏感的部分已经过优化或设计时已考虑到优化。WebSocket 处理的缓慢部分已得到优化，而 HTTP 解析器的设计借鉴自另一个以性能为设计目标的极受欢迎的项目（参见 [@https://github.com/h2o/picohttpparser]）。

引自：[@http://www.boost.org/development/requirements.html]

“在大多数 Boost 库中，首先应追求清晰和正确；优化应仅是次要关注点。”

随着库的成熟，它将经历优化阶段；基准测试自然会伴随这一过程。测试中包含一个小型基准测试程序，用于比较 Beast 解析器与 NodeJS 参考解析器的性能，以及一些比较各种 Beast 动态缓冲区实现与 Asio 性能的基准测试。
]]
[[“Beast 这个名字太糟糕了！”
][“Boost.Http”或“Boost.WebSocket”这样的名称会误导用户，让他们以为只需几行代码就能通过 URL 发起 HTTP 请求，或搭建一个 WebSocket 客户端或服务器。那么，核心工具该放在哪里呢？如果将内容放入 boost/asio 目录，很可能会冒犯 Boost.Asio 的维护者；至少也会给该外部仓库带来不必要的额外工作。

“Beast”这个名字足够模糊，不会暗示任何特定的功能，同时又作为一个令人印象深刻的总括术语，涵盖了一系列底层的容器和算法。了解该库或有底层网络协议操作需求的人很容易找到它，而将新手诱入糟糕体验的可能性则大大降低。使用专有名称是有先例的：“Hana”、“Fusion”、“Phoenix”和“Spirit”都是例子。例如，“Beast”真的比“mp11”更糟糕吗？此外，Beast 已经拥有越来越多的用户，并受到开源社区的关注；在 Reddit 帖子和 StackOverflow 上，当人们询问该使用哪个 HTTP 或 WebSocket 库时，Beast 经常作为答案出现。
]]



[[“再多一些高级示例会有帮助，比如包含带有客户端/服务器证书的 TLS 的示例。”
][server-framework 示例演示了如何实现一个使用证书支持 TLS 的服务器。此外，还有使用 TLS 的 WebSocket 和 HTTP 客户端示例。而且，证书管理超出了该库公共接口的范畴。Asio 已经提供了执行这些任务的文档、接口和示例——Beast 不打算重新发明它们，也不打算冗余地提供这些信息。
]]

[[“内置的 HTTP 路由器？”
][我们理解这指的是一个用于将表达式与 HTTP 请求中的 URI 进行匹配，并将其分派给调用代码的机制。作者认为这是更高层代码的职责。Beast 并不试图提供一个 Web 服务器。话虽如此，server-framework 示例中提供了一个名为 Service 的请求路由概念。该示例提供了两种服务，一种用于提供文件服务，另一种用于处理 WebSocket 升级请求。
]]

[[“HTTP Cookies？表单/文件上传？”
][“Cookie，或者说一般性地管理这类 HTTP 头部，属于更高层级的职责。Beast 只是尽量将完整的消息传递到调用代码中或从调用代码中传出。它对 HTTP 头部的处理仅限于解析消息体所需的程度，其余部分则留给调用者自行处理。不过，对于表单和文件上传，消息类的对称接口允许 HTTP 请求包含任意的消息体类型，包括上传文件或填写表单所需的类型。”
]]

[[“……支持 TLS（这是一个功能吗？如果不是，这将是一个致命缺陷），等等。”
][Beast 基于 Stream 概念，因此能自动兼容通过 Asio 已配置好的 `boost::asio::ssl::stream`。
]]

[[“还应提供更多示例，展示如何将 HTTP 服务与从文件系统获取文件、生成 CGI 风格的响应进行集成。”
][该库的设计目标并非试图构建一个 Web 服务器。我们深感需要一种基础实现，用于对 HTTP 消息进行建模，并提供通过 Asio 发送和接收这些消息的函数。此类实现应作为构建块，用于构建前述 HTTP 服务或 CGI 网关等更高级别的抽象。

在示例目录中，存在多个用于提供文件服务的 HTTP 服务器，以及部分经过测试和编译的代码片段，这些内容可作为与其他进程进行交互的起点。
]]

[[“如果确实需要，应当发送 100-continue 以请求剩余的请求体。”
][是否发送 "Expect: 100-continue" 头部，或者如何在服务端处理该头部，均由调用者自行负责；Beast 提供相应的功能，用于在发送或读取消息体之前发送或检查该头部。
]]



[[“我也希望看到该库在生产环境中使用的实例。这将为其设计在实践中切实可行提供佐证。”
][Beast 已部署于公开服务器，接收流量并每日处理价值数亿美元的金融交易。这些服务器运行的是 *rippled*，这是一款开源软件（[@https://github.com/ripple/rippled repository]），实现了 [@https://ripple.com/files/ripple_consensus_whitepaper.pdf *Ripple Consensus Protocol*]，该技术由 [@http://ripple.com Ripple] 提供。

此外，该仓库在 2017 年人气显著增长。目前存在大量用户，其中部分用户通过报告问题、执行测试，甚至在某些情况下提交包含代码贡献的拉取请求，直接参与仓库的维护。
]]



[[那 WebSocket 消息压缩呢？
][Beast WebSocket 支持 [@https://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-00 draft-ietf-hybi-permessage-compression-00] 中描述的 permessage-deflate 扩展。该库附带一个仅含头文件的 C++11 版本 ZLib "deflate" 编解码器，用于实现 permessage-deflate 扩展。
]]
[[WebSocket TLS/SSL 接口位于何处？
][`websocket::stream` 对传入的套接字或流（例如 `boost::asio::ip::tcp::socket` 或 `boost::asio::ssl::stream`）进行封装。使用 `ssl::stream` 的接口建立 TLS 连接（如所有 Asio 示例所示），随后围绕该连接构建 `websocket::stream`。

WebSocket 实现确实支持关闭 TLS 连接，该操作通过 ADL 编译期虚函数 [link beast.ref.boost__beast__websocket__teardown `teardown`] 和 [link beast.ref.boost__beast__websocket__async_teardown `async_teardown`] 进行。这些函数针对 TLS 流提供了重载，能够按照 rfc6455 规范正确关闭连接。针对用户自定义的底层流类型，调用者可以提供这些函数的自定义重载。
]]
[[Windows 与 OpenSSL：如何在 Microsoft Windows 上安装并使用 OpenSSL 进行构建？
][一种简便方法是使用命令行包管理器 Chocolatey 或 Scoop。示例如下：`choco install -y openssl --x86 --version 1.1.1.700` 或 `scoop install openssl@1.1.1g -a 32bit -g`

如果将 OpenSSL 安装到了名称包含空格的目录中，建议创建符号链接以使用更简单的路径，例如：
`mklink /D "OpenSSL" "Program Files (x86)\\OpenSSL-Win32"`

将环境变量 `OPENSSL_ROOT` 设置为新安装目录的位置：
`set OPENSSL_ROOT=C:/OpenSSL`

随后进行构建。有关使用 OpenSSL 构建测试用例的示例，请参考 `beast/.dockers/windows-vs-32/Dockerfile`。
]]
]

[endsect]
